Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • paulmc/fslpy
  • ndcn0236/fslpy
  • seanf/fslpy
3 results
Show changes
Showing
with 643 additions and 37 deletions
......@@ -10,7 +10,7 @@ import textwrap
import pytest
from . import testdir
from fsl.tests import testdir
import fsl.version as fslversion
......
......@@ -6,15 +6,20 @@
#
import os.path as op
import shutil
import tempfile
import os.path as op
import textwrap as tw
import io
import shutil
import tempfile
import warnings
import numpy as np
import pytest
import numpy as np
import pytest
import fsl.data.vest as vest
from fsl.tests import tempdir
testfile1 = """%!VEST-LUT
%%BeginInstance
......@@ -110,11 +115,37 @@ testfile4Colours = np.array([
testfile5 = """Obviously not a VEST file"""
testfile6 = """%BeginInstance
/SavedInstanceClassName /ClassLUT
/PseudoColourmap [
<-color{0.0,1.0,5.0}->
<-color{1.0,2.0,4.0}->
<-color{2.0,3.0,3.0}->
]
>>
%%EndInstance
%%EOF
"""
testfile7 = """%%BeginInstance
/SavedInstanceClassName /ClassLUT
/PseudoColourmap [
<-color{0.0,1.0,5.0}->
<-color{1.0,2.0,4.0}->
<-color{2.0,3.0,3.0}->
]
>>
%%EndInstance
%%EOF
"""
def _createFiles(testdir):
names = ['testfile1', 'testfile2', 'testfile3', 'testfile4', 'testfile5']
texts = [ testfile1, testfile2, testfile3, testfile4, testfile5]
names = ['testfile1', 'testfile2', 'testfile3', 'testfile4', 'testfile5',
'testfile6', 'testfile7']
texts = [ testfile1, testfile2, testfile3, testfile4, testfile5,
testfile6, testfile7]
for name, text in zip(names, texts):
filename = op.join(testdir, '{}.txt'.format(name))
......@@ -136,6 +167,8 @@ def test_looksLikeVestLutFile():
assert vest.looksLikeVestLutFile(op.join(testdir, 'testfile3.txt'))
assert vest.looksLikeVestLutFile(op.join(testdir, 'testfile4.txt'))
assert not vest.looksLikeVestLutFile(op.join(testdir, 'testfile5.txt'))
assert vest.looksLikeVestLutFile(op.join(testdir, 'testfile6.txt'))
assert vest.looksLikeVestLutFile(op.join(testdir, 'testfile7.txt'))
finally:
shutil.rmtree(testdir)
......@@ -166,9 +199,12 @@ def test_loadVestLutFile():
for i in range(4):
f = testfiles[i]
d = testdata[ i]
dnorm = (d - d.min()) / (d.max() - d.min())
lutnorm = vest.loadVestLutFile(f)
lut = vest.loadVestLutFile(f, normalise=False)
with warnings.catch_warnings():
warnings.simplefilter('ignore')
dnorm = (d - d.min()) / (d.max() - d.min())
lutnorm = vest.loadVestLutFile(f)
lut = vest.loadVestLutFile(f, normalise=False)
assert lut.shape == d.shape
assert lutnorm.shape == dnorm.shape
......@@ -182,3 +218,75 @@ def test_loadVestLutFile():
finally:
shutil.rmtree(testdir)
def test_generateVest():
def readvest(vstr):
lines = vstr.split('\n')
nrows = [l for l in lines if 'NumPoints' in l][0]
ncols = [l for l in lines if 'NumWaves' in l][0]
nrows = int(nrows.split()[1])
ncols = int(ncols.split()[1])
data = '\n'.join(lines[3:])
data = np.loadtxt(io.StringIO(data)).reshape((nrows, ncols))
return ((nrows, ncols), data)
# shape, expectedshape
tests = [
((10, ), ( 1, 10)),
((10, 1), (10, 1)),
(( 1, 10), ( 1, 10)),
(( 3, 5), ( 3, 5)),
(( 5, 3), ( 5, 3))
]
for shape, expshape in tests:
data = np.random.random(shape)
vstr = vest.generateVest(data)
gotshape, gotdata = readvest(vstr)
data = data.reshape(expshape)
assert expshape == gotshape
assert np.all(np.isclose(data, gotdata))
def test_loadVestFile():
def genvest(data, path, shapeOverride=None):
if shapeOverride is None:
nrows, ncols = data.shape
else:
nrows, ncols = shapeOverride
with open(path, 'wt') as f:
f.write(f'/NumWaves {ncols}\n')
f.write(f'/NumPoints {nrows}\n')
f.write( '/Matrix\n')
if np.issubdtype(data.dtype, np.integer): fmt = '%d'
else: fmt = '%0.12f'
np.savetxt(f, data, fmt=fmt)
with tempdir():
data = np.random.randint(1, 100, (10, 20))
genvest(data, 'data.vest')
assert np.all(data == vest.loadVestFile('data.vest'))
data = np.random.random((20, 10))
genvest(data, 'data.vest')
assert np.all(np.isclose(data, vest.loadVestFile('data.vest')))
# should pass
vest.loadVestFile('data.vest', ignoreHeader=False)
# invalid VEST header
genvest(data, 'data.vest', (10, 20))
# default behaviour - ignore header
assert np.all(np.isclose(data, vest.loadVestFile('data.vest')))
with pytest.raises(ValueError):
vest.loadVestFile('data.vest', ignoreHeader=False)
......@@ -11,29 +11,29 @@ import textwrap
import pytest
import tests
import fsl.tests as tests
import fsl.data.fixlabels as fixlbls
import fsl.data.volumelabels as vollbls
def test_add_get_hasLabel():
ncomps = 5
labels = ['Label {}'.format(i) for i in range(ncomps)]
lowers = [lbl.lower() for lbl in labels]
lblobj = vollbls.VolumeLabels(ncomps)
called = [False]
def labelAdded(lo, topic, value):
called[0] = True
lblobj.register('callback', labelAdded, topic='added')
for i in range(ncomps):
called[0] = False
assert lblobj.addLabel(i, labels[i])
assert called[0]
assert lblobj.getLabels(i) == [lowers[i]]
......@@ -47,7 +47,7 @@ def test_add_get_hasLabel():
called[0] = False
assert not lblobj.addLabel(i, labels[i])
assert not called[0]
# Labels are case insensitive
assert not lblobj.addLabel(i, lowers[i])
assert not called[0]
......@@ -56,7 +56,7 @@ def test_add_get_hasLabel():
def test_removeLabel():
ncomps = 5
labels = ['Label {}'.format(i) for i in range(ncomps)]
lowers = [lbl.lower() for lbl in labels]
......@@ -66,7 +66,7 @@ def test_removeLabel():
lblobj.addLabel(i, labels[i])
called = [False]
def removed(*a):
called[0] = True
......@@ -80,14 +80,14 @@ def test_removeLabel():
called[0] = False
assert lblobj.removeLabel(i, labels[i])
assert called[0]
assert called[0]
assert lblobj.getLabels(i) == []
assert sorted(lblobj.getAllLabels()) == lowers[i + 1:]
def test_clearLabels():
ncomps = 5
labels = [('Label {}'.format(i), 'Label b')
for i in range(ncomps)]
......@@ -99,7 +99,7 @@ def test_clearLabels():
lblobj.addLabel(i, l)
calledValue = []
def removed(lo, topic, value):
calledValue.append(value)
......@@ -125,14 +125,14 @@ def test_add_get_hasComponents():
lblobj = vollbls.VolumeLabels(ncomps)
called = [False]
def labelAdded(lo, topic, value):
called[0] = True
lblobj.register('callback', labelAdded, topic='added')
for i in range(ncomps):
called[0] = False
assert lblobj.addComponent(labels[i], i)
assert called[0]
......@@ -167,8 +167,8 @@ def test_removeComponent():
called[0] = False
assert lblobj.removeComponent(labels[i], i)
assert called[0]
assert called[0]
assert lblobj.getComponents(labels[i]) == []
assert sorted(lblobj.getAllLabels()) == labels[i + 1:]
......@@ -184,7 +184,7 @@ def test_clearComponents():
lblobj.addLabel(i, l)
calledValue = []
def removed(lo, topic, value):
calledValue.append(value)
......@@ -199,11 +199,11 @@ def test_clearComponents():
labels = [l[0] for l in labels]
for i in range(ncomps):
calledValue = []
lblobj.clearComponents(labels[i])
assert calledValue[0] == [(i, labels[i])]
assert lblobj.getComponents(labels[i]) == []
assert lblobj.getLabels(i) == []
......@@ -250,7 +250,7 @@ def test_load_fixfile_long():
lblobj = vollbls.VolumeLabels(4)
lblobj.load(fname)
for i in range(4):
assert lblobj.getLabels(i) == expected[i]
assert lblobj.getLabels(i) == expected[i]
def test_load_fixfile_short():
......@@ -285,7 +285,7 @@ def test_load_fixfile_short():
lblobj = vollbls.VolumeLabels(5)
lblobj.load(fname)
for i in range(4):
assert lblobj.getLabels(i) == expected[i]
assert lblobj.getLabels(i) == expected[i]
def test_load_aromafile():
......@@ -320,7 +320,7 @@ def test_load_aromafile():
lblobj = vollbls.VolumeLabels(5)
lblobj.load(fname)
for i in range(4):
assert lblobj.getLabels(i) == expected[i]
assert lblobj.getLabels(i) == expected[i]
def test_save():
......@@ -341,15 +341,15 @@ def test_save():
lbls.addLabel(3, 'Movement')
with tests.testdir() as testdir:
fname = op.join(testdir, 'labels.txt')
# Test saving without dirname
lbls.save(fname)
exp = '.\n{}'.format(expected)
exp = '.\n{}'.format(expected)
with open(fname, 'rt') as f:
assert f.read().strip() == exp.strip()
# And with dirname
lbls.save(fname, 'path/to/analysis.ica')
exp = 'path/to/analysis.ica\n{}'.format(expected)
......
File moved
#!/usr/bin/env python
import contextlib
import os.path as op
import itertools as it
import fsl.utils.assertions as asrt
import fsl.utils.run as run
from fsl.tests import mockFSLDIR
def checkResult(cmd, base, args, stripdir=None):
"""Check that the generate dcommand matches the expected command.
Pre python 3.7, we couldn't control the order in which command
line args were generated, so we needed to test all possible orderings.
But for Python >= 3.7, the order in which kwargs are passed will
be the same as the order in which they are rendered, so this function
is not required.
:arg cmd: Generated command
:arg base: Beginning of expected command
:arg args: Sequence of expected arguments
:arg stripdir: Sequence of indices indicating arguments
for whihc any leading directory should be ignored.
"""
if stripdir is not None:
cmd = list(cmd.split())
for si in stripdir:
cmd[si] = op.basename(cmd[si])
cmd = ' '.join(cmd)
permutations = it.permutations(args, len(args))
possible = [' '.join([base] + list(p)) for p in permutations]
return any([cmd == p for p in possible])
@contextlib.contextmanager
def testenv(*fslexes):
with asrt.disabled(), run.dryrun(), mockFSLDIR(bin=fslexes) as fsldir:
fslexes = [op.join(fsldir, 'bin', e) for e in fslexes]
if len(fslexes) == 1: yield fslexes[0]
else: yield fslexes
testenv.__test__ = False
#!/usr/bin/env python
#
# test_cluster.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import contextlib
import os
import os.path as op
import sys
import textwrap as tw
from unittest import mock
import numpy as np
from fsl.wrappers import wrapperutils as wutils
from fsl.wrappers.cluster_commands import (cluster,
_cluster,
smoothest,
_smoothest)
from fsl.tests.test_wrappers import testenv
from fsl.tests import mockFSLDIR
@contextlib.contextmanager
def reseed(seed):
state = np.random.get_state()
np.random.seed(seed)
try:
yield
finally:
np.random.set_state(state)
def test_cluster_wrapper():
with testenv('fsl-cluster') as cluster_exe:
result = _cluster('input', 10, mm=True)
expected = [cluster_exe, '-i', 'input', '-t', '10', '--mm']
expected = ' '.join(expected)
assert result.stdout[0] == expected
mock_titles = 'ABCDEFGHIJ'
mock_cluster = f"""
#!/usr/bin/env python
import numpy as np
np.random.seed(12345)
data = np.random.randint(1, 10, (10, 10))
print('\t'.join('{mock_titles}'))
for row in data:
print('\t'.join([str(val) for val in row]))
""".strip()
def test_cluster():
with mockFSLDIR() as fsldir:
cluster_exe = op.join(fsldir, 'bin', 'fsl-cluster')
with open(cluster_exe, 'wt') as f:
f.write(mock_cluster)
os.chmod(cluster_exe, 0o755)
data, titles, result1 = cluster('input', 3.5)
result2 = cluster('input', 3.5, load=False)
with reseed(12345):
expected = np.random.randint(1, 10, (10, 10))
assert np.all(np.isclose(data, expected))
assert ''.join(titles) == mock_titles
assert result1.stdout == result2.stdout
def test_smoothest_wrapper():
with testenv('smoothest') as smoothest_exe:
result = _smoothest(res='res', zstat='zstat', d=5, V=True)
expected = f'{smoothest_exe} --res=res --zstat=zstat -d 5 -V'
assert result.stdout[0] == expected
# auto detect residuals vs zstat
result = _smoothest('res4d.nii.gz', d=5, V=True)
expected = f'{smoothest_exe} -d 5 -V --res=res4d.nii.gz'
assert result.stdout[0] == expected
result = _smoothest('zstat1.nii.gz', d=5, V=True)
expected = f'{smoothest_exe} -d 5 -V --zstat=zstat1.nii.gz'
assert result.stdout[0] == expected
def test_smoothest():
result = tw.dedent("""
FWHMx = 4.763 mm, FWHMy = 5.06668 mm, FWHMz = 4.71527 mm
DLH 0.324569 voxels^-3
VOLUME 244531 voxels
RESELS 14.224 voxels per resel
DLH 0.324569
VOLUME 244531
RESELS 14.224
FWHMvoxel 2.3815 2.53334 2.35763
FWHMmm 4.763 5.06668 4.71527
""")
result = wutils.FileOrThing.Results((result, ''))
expect = {
'DLH' : 0.324569,
'VOLUME' : 244531,
'RESELS' : 14.224,
'FWHMvoxel' : [2.3815, 2.53334, 2.35763],
'FWHMmm' : [4.763, 5.06668, 4.71527]
}
with mock.patch('fsl.wrappers.cluster_commands._smoothest',
return_value=result):
result = smoothest('inimage')
assert result.keys() == expect.keys()
assert np.isclose(result['DLH'], expect['DLH'])
assert np.isclose(result['VOLUME'], expect['VOLUME'])
assert np.isclose(result['RESELS'], expect['RESELS'])
assert np.all(np.isclose(result['FWHMvoxel'], expect['FWHMvoxel']))
assert np.all(np.isclose(result['FWHMmm'], expect['FWHMmm']))
#!/usr/bin/env python
import glob
import os
import os.path as op
import multiprocessing as mp
import random
import shutil
import time
from fsl.data.image import removeExt
from fsl.utils.tempdir import tempdir
import fsl.wrappers.wrapperutils as wutils
datadir = op.join(op.dirname(__file__), '..', 'testdata')
@wutils.fileOrImage('infile')
@wutils.fileOrImage('outfile')
def myfunc(infile, outfile):
time.sleep(1 + random.random() * 2)
shutil.copy(infile, outfile)
# fsl/fslpy!446
def test_wrappers_concurrent():
exfunc = op.join(datadir, 'example_func.nii.gz')
with tempdir():
for i in range(1, 11):
shutil.copy(exfunc, f'{i:02d}.nii.gz')
infiles = list(glob.glob('??.nii.gz'))
basenames = [removeExt(f) for f in infiles]
outfiles = [f'{bn}_brain.nii.gz' for bn in basenames]
with mp.Pool(len(infiles)) as pool:
args = zip(infiles, outfiles)
pool.starmap(myfunc, args)
assert all(op.exists(f) for f in outfiles)
#!/usr/bin/env python
#
# test_fslio.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import os.path as op
from unittest import mock
from fsl.utils.tempdir import tempdir
from fsl.tests import make_random_image
import fsl.wrappers as fw
def test_fslio_wrappers():
with tempdir(), mock.patch.dict('os.environ', FSLOUTPUTTYPE='NIFTI_GZ'):
make_random_image('image.nii.gz')
fw.imcp('image', 'image2')
assert op.exists('image2.nii.gz')
fw.imln('image', 'imagelink')
assert op.islink('imagelink.nii.gz')
fw.immv('image2', 'image3')
assert not op.exists('image2.nii.gz')
assert op.exists('image3.nii.gz')
assert sorted(fw.imglob('image*')) == ['image', 'image3', 'imagelink']
fw.imrm('image3')
assert not op.exists('image3.nii.gz')
assert fw.imtest('image')
#!/usr/bin/env python
#
# test_fslmaths.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import os
import os.path as op
import textwrap as tw
import numpy as np
from fsl.utils.tempdir import tempdir
import fsl.wrappers as fw
from fsl.tests import mockFSLDIR, make_random_image
from fsl.tests.test_wrappers import testenv
def test_fslmaths():
with testenv('fslmaths') as fslmaths:
result = fw.fslmaths('input') \
.range() \
.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) \
.smooth(sigma=6).kernel('3D').fmeanu().roi(10, 3, 20, 21, 1, 5) \
.sqr().sqrt().log().dilD(2).max('im').min('im2') \
.fmedian().kernel('3D').kernel('box', 3) \
.run('output')
expected = [fslmaths, 'input', '-range',
'-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', '-s 6', '-kernel 3D', '-fmeanu',
'-roi 10 3 20 21 1 5 0 -1', '-sqr', '-sqrt', '-log',
'-dilD', '-dilD', '-max', 'im', '-min', 'im2', '-fmedian',
'-kernel', '3D', '-kernel', 'box', '3', 'output']
expected = ' '.join(expected)
assert result.stdout[0] == expected
def test_fslmaths2():
with testenv('fslmaths') as fslmaths:
result = fw.fslmaths('input') \
.thrp(20).thrP(50).uthrp(75).uthrP(90).seed(1234).restart('input2') \
.save('temp').exp().log().sin().cos().tan().asin().acos().atan() \
.recip().fillh26().index().grid(1, 2).edge().dog_edge(1, 2) \
.tfce(1, 2, 3).tfceS(1, 2, 3, 4, 5, 6, 7).nan().nanm().rand() \
.randn().ing('ingim').tensor_decomp().dilD(3).eroF(2).fmedian() \
.fmean().s(5).subsamp2().subsamp2offc().run('output')
expected = f'{fslmaths} input -thrp 20 -thrP 50 -uthrp 75 -uthrP 90 ' \
'-seed 1234 -restart input2 -save temp -exp -log -sin ' \
'-cos -tan -asin -acos -atan -recip -fillh26 -index ' \
'-grid 1 2 -edge -dog_edge 1 2 -tfce 1 2 3 -tfceS 1 2 3 4 ' \
'5 6 7 -nan -nanm -rand -randn -ing ingim -tensor_decomp ' \
'-dilD -dilD -dilD -eroF -eroF -fmedian -fmean -s 5 ' \
'-subsamp2 -subsamp2offc output'
assert result.stdout[0] == expected
def test_fslmaths3():
with testenv('fslmaths') as fslmaths:
result = fw.fslmaths('input') \
.Tmean().Tstd().Tmin().Tmax().Tmaxn().Tmedian().Tperc(50).Tar1() \
.pval().pval0().cpval().ztop().ptoz().rank().ranknorm() \
.run('output')
expected = f'{fslmaths} input -Tmean -Tstd -Tmin -Tmax -Tmaxn ' \
'-Tmedian -Tperc 50 -Tar1 -pval -pval0 -cpval -ztop ' \
'-ptoz -rank -ranknorm output'
assert result.stdout[0] == expected
def test_fslmaths_load():
with testenv('fslmaths') as fslmaths:
result = fw.fslmaths('input', 'char').ero().ero().bin()\
.run('output', 'float')
expected = f'{fslmaths} -dt char input -ero -ero -bin ' \
'output -odt float'
assert result.stdout[0] == expected
def test_fslmaths_load():
with tempdir() as td, mockFSLDIR(bin=('fslmaths',)) as fsldir:
expect = make_random_image(op.join(td, 'output.nii.gz'))
with open(op.join(fsldir, 'bin', 'fslmaths'), 'wt') as f:
f.write(tw.dedent("""
#!/usr/bin/env python
import sys
import shutil
shutil.copy('{}', sys.argv[2])
""".format(op.join(td, 'output.nii.gz'))).strip())
os.chmod(op.join(fsldir, 'bin', 'fslmaths'), 0o755)
got = fw.fslmaths('input').run()
assert np.all(expect.dataobj[:] == got.dataobj[:])
got = fw.fslmaths('input').run(fw.LOAD)
assert np.all(expect.dataobj[:] == got.dataobj[:])
#!/usr/bin/env python
import os
import os.path as op
import textwrap as tw
import sys
import contextlib
import pytest
import numpy as np
import fsl.utils.run as run
import fsl.utils.tempdir as tempdir
import fsl.wrappers as fw
from fsl.tests import mockFSLDIR as mockFSLDIR_base, make_random_image
mock_fslstats = """
#!/usr/bin/env python3
shape = {outshape}
import sys
import numpy as np
data = np.random.randint(1, 10, shape)
if len(shape) == 1:
data = data.reshape(1, -1)
np.savetxt(sys.stdout, data, fmt='%i')
""".strip()
@contextlib.contextmanager
def mockFSLDIR(shape=None, fslstats=None):
with mockFSLDIR_base() as fd:
fname = op.join(fd, 'bin', 'fslstats')
if shape is not None:
script = mock_fslstats.format(outshape=shape)
else:
script = fslstats
with open(fname, 'wt') as f:
f.write(script)
os.chmod(fname, 0o755)
yield fd
def test_fslstats_cmdline():
with tempdir.tempdir(), run.dryrun(), mockFSLDIR(1) as fsldir:
make_random_image('image')
cmd = op.join(fsldir, 'bin', 'fslstats')
result = fw.fslstats('image').m.r.mask('mask').k('mask').r.run(True)
expected = cmd + ' image -m -r -k mask -k mask -r'
assert result[0] == expected
result = fw.fslstats('image', t=True, K='mask').m.R.u(123).s.volume.run(True)
expected = cmd + ' -t -K mask image -m -R -u 123 -s -v'
assert result[0] == expected
result = fw.fslstats('image', K='mask').n.V.p(1).run(True)
expected = cmd + ' -K mask image -n -V -p 1'
assert result[0] == expected
result = fw.fslstats('image', t=True).H(10, 1, 99).d('diff').run(True)
expected = cmd + ' -t image -H 10 1 99 -d diff'
assert result[0] == expected
# unknown option
with pytest.raises(AttributeError):
fw.fslstats('image').Q
def test_fslstats_result():
with tempdir.tempdir():
with mockFSLDIR('(1,)') as fsldir:
result = fw.fslstats('image').run()
assert np.isscalar(result)
with mockFSLDIR('(2,)') as fsldir:
result = fw.fslstats('image').run()
assert result.shape == (2,)
# 3 mask lbls, 2 values
with mockFSLDIR('(3, 2)') as fsldir:
result = fw.fslstats('image', K='mask').run()
assert result.shape == (3, 2)
# 5 vols, 2 values
with mockFSLDIR('(5, 2)') as fsldir:
result = fw.fslstats('image', t=True).run()
assert result.shape == (5, 2)
# 5 vols, 3 mask lbls, 2 values
with mockFSLDIR('(15, 2)') as fsldir:
make_random_image('image', (10, 10, 10, 5))
result = fw.fslstats('image', K='mask', t=True).run()
assert result.shape == (5, 3, 2)
# -t/-K with a 3D image
with mockFSLDIR('(4,)') as fsldir:
make_random_image('image', (10, 10, 10))
result = fw.fslstats('image', K='mask', t=True).run()
assert result.shape == (4,)
result = fw.fslstats('image', t=True).run()
assert result.shape == (4,)
result = fw.fslstats('image', K='mask').run()
assert result.shape == (4,)
def test_fslstats_index_mask_missing_labels():
script = tw.dedent("""
#!/usr/bin/env bash
echo "1"
echo "missing label: 2"
echo "3"
echo "missing label: 4"
echo "5"
""").strip()
with tempdir.tempdir():
with mockFSLDIR(fslstats=script) as fsldir:
result = fw.fslstats('image', K='mask').p(50).run()
expect = np.array([1, np.nan, 3, np.nan, 5])
namask = np.isnan(expect)
assert np.all(result[~namask] == expect[~namask])
assert np.all(np.isnan(expect) == np.isnan(result))