Skip to content
Snippets Groups Projects
Commit 16056e41 authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

Merge branch 'bf/cluster' into 'master'

Bf/cluster

See merge request fsl/fslpy!281
parents d7fb61b6 7cc03ad2
No related branches found
No related tags found
No related merge requests found
Pipeline #7740 passed
......@@ -2,6 +2,17 @@ This document contains the ``fslpy`` release history in reverse chronological
order.
3.5.3 (Tuesday 9th February 2021)
---------------------------------
Fixed
^^^^^
* Fixed a bug in :func:`.featanalysis.loadClusterResults` (!281).
3.5.2 (Friday 29th January 2021)
---------------------------------
......@@ -12,8 +23,8 @@ Fixed
* Adjusted the :func:`.dicom.scanDir` function so that it will set a
default value for ``SeriesDescription`` if it is not present in the
``dcm2niix`` ``json`` output.
* Fixed some issues with API documentation generation.
``dcm2niix`` ``json`` output (!279).
* Fixed some issues with API documentation generation (!279).
3.5.1 (Thursday 21st January 2021)
......
......@@ -373,7 +373,7 @@ def loadClusterResults(featdir, settings, contrast):
if not op.exists(clusterFile):
return None
# In higher levle analysis run in some standard
# In higher level analysis run in some standard
# space, the cluster coordinates are in standard
# space. We transform them to voxel coordinates.
# later on.
......@@ -480,13 +480,13 @@ def loadClusterResults(featdir, settings, contrast):
zcog = [c.zcogx, c.zcogy, c.zcogz]
copemax = [c.copemaxx, c.copemaxy, c.copemaxz]
zmax = affine.transform([zmax], coordXform)[0].round()
zcog = affine.transform([zcog], coordXform)[0].round()
copemax = affine.transform([copemax], coordXform)[0].round()
zmax = affine.transform([zmax], coordXform)[0]
zcog = affine.transform([zcog], coordXform)[0]
copemax = affine.transform([copemax], coordXform)[0]
c.zmaxx, c.zmaxy, c.zmaxz = zmax
c.zcogx, c.zcogy, c.zcogz = zcog
c.copemax, c.copemaxy, c.copemaxz = copemax
c.zmaxx, c.zmaxy, c.zmaxz = zmax
c.zcogx, c.zcogy, c.zcogz = zcog
c.copemaxx, c.copemaxy, c.copemaxz = copemax
return clusters
......
......@@ -59,7 +59,7 @@ def test_isFEATDir():
# it's not a feat directory
assert not featanalysis.isFEATDir('nonexistent.feat')
# If any of the above files are not
# If any of the above files are not
# present, it is not a FEAT directory
perms = it.chain(it.combinations(paths, 1),
it.combinations(paths, 2),
......@@ -69,7 +69,7 @@ def test_isFEATDir():
assert not featanalysis.isFEATDir(
op.join(testdir, 'analysis.feat'))
def test_hasStats():
with tests.testdir(['analysis.feat/stats/zstat1.nii.gz']) as testdir:
......@@ -78,7 +78,7 @@ def test_hasStats():
with tests.testdir(['analysis.feat/stats/zstat1.txt']) as testdir:
featdir = op.join(testdir, 'analysis.feat')
assert not featanalysis.hasStats(featdir)
assert not featanalysis.hasStats(featdir)
def test_hasMelodicDir():
......@@ -94,7 +94,7 @@ def test_getAnalysisDir():
'analysis.feat/design.fsf',
'analysis.feat/design.mat',
'analysis.feat/design.con']
testpaths = ['analysis.feat/filtered_func_data.nii.gz',
'analysis.feat/stats/zstat1.nii.gz',
'analysis.feat/logs/feat4_post',
......@@ -106,7 +106,7 @@ def test_getAnalysisDir():
t = op.join(testdir, t)
assert featanalysis.getAnalysisDir(t) == expected
def test_getTopLevelAnalysisDir():
testcases = [
('analysis.feat/filtered_func_data.ica/melodic_IC.nii.gz', 'analysis.feat'),
......@@ -127,7 +127,7 @@ def test_getReportFile():
for paths, expected in testcases:
with tests.testdir(paths) as testdir:
featdir = op.join(testdir, 'analysis.feat')
if expected:
......@@ -145,7 +145,7 @@ def test_loadContrasts():
/ContrastName1 c1
/ContrastName2 c2
/ContrastName3 c3
/NumContrasts 3
/NumContrasts 3
/Matrix
1 0 0
0 1 0
......@@ -188,9 +188,9 @@ def test_loadContrasts():
0 1 1
""",
]
with pytest.raises(Exception):
featanalysis.loadContrasts('no file')
featanalysis.loadContrasts('no file')
with tests.testdir() as testdir:
featdir = op.join(testdir, 'analysis.feat')
......@@ -275,7 +275,7 @@ def test_isFirstLevelAnalysis():
'2ndlevel_1.gfeat', '2ndlevel_2.gfeat']
for featdir in featdirs:
expected = featdir.startswith('1')
featdir = op.join(datadir, featdir)
settings = featanalysis.loadSettings(featdir)
......@@ -301,14 +301,15 @@ def test_loadClusterResults():
with tests.testdir() as testdir:
# For higher level analyses, the
# loadClusterResults function peeks
# at the FEAT input data file
# header, so we have to generate it.
# work from a copy of the test data directory
newfeatdir = op.join(testdir, 'analysis.feat')
shutil.copytree(op.join(datadir, featdir), newfeatdir)
featdir = newfeatdir
# For higher level analyses, the
# loadClusterResults function peeks
# at the FEAT input data file
# header, so we have to generate it.
if not firstlevel:
datafile = op.join(featdir, 'filtered_func_data.nii.gz')
data = np.random.randint(1, 10, (91, 109, 91))
......@@ -333,6 +334,35 @@ def test_loadClusterResults():
assert featanalysis.loadClusterResults(
featdir, settings, 0) is None
# The above loop just checks that the number of
# clusters loaded for each analysis was correct.
# Below we check that the cluster data was loaded
# correctly, just for one analysis
featdir = op.join(datadir, '1stlevel_1.feat')
settings = featanalysis.loadSettings(featdir)
cluster = featanalysis.loadClusterResults(featdir, settings, 0)[0]
expected = {
'index' : 1,
'nvoxels' : 296,
'p' : 1.79e-27,
'logp' : 26.7,
'zmax' : 6.03,
'zmaxx' : 34,
'zmaxy' : 10,
'zmaxz' : 1,
'zcogx' : 31.4,
'zcogy' : 12.3,
'zcogz' : 1.72,
'copemax' : 612,
'copemaxx' : 34,
'copemaxy' : 10,
'copemaxz' : 1,
'copemean' : 143
}
for k, v in expected.items():
assert np.isclose(v, getattr(cluster, k))
def test_getDataFile():
paths = ['analysis.feat/filtered_func_data.nii.gz',
......@@ -393,9 +423,9 @@ def test_getResidualFile():
assert featanalysis.getResidualFile(featdir) == expect
else:
with pytest.raises(fslpath.PathError):
featanalysis.getResidualFile(featdir)
featanalysis.getResidualFile(featdir)
def test_getPEFile():
testcases = [
(['analysis.feat/stats/pe1.nii.gz',
......@@ -417,7 +447,7 @@ def test_getPEFile():
assert featanalysis.getPEFile(featdir, pei) == expect
else:
with pytest.raises(fslpath.PathError):
featanalysis.getPEFile(featdir, pei)
featanalysis.getPEFile(featdir, pei)
def test_getCOPEFile():
......@@ -441,8 +471,8 @@ def test_getCOPEFile():
assert featanalysis.getCOPEFile(featdir, ci) == expect
else:
with pytest.raises(fslpath.PathError):
featanalysis.getCOPEFile(featdir, ci)
featanalysis.getCOPEFile(featdir, ci)
def test_getZStatFile():
testcases = [
......@@ -465,8 +495,8 @@ def test_getZStatFile():
assert featanalysis.getZStatFile(featdir, zi) == expect
else:
with pytest.raises(fslpath.PathError):
featanalysis.getZStatFile(featdir, zi)
featanalysis.getZStatFile(featdir, zi)
def test_getClusterMaskFile():
testcases = [
......@@ -489,4 +519,4 @@ def test_getClusterMaskFile():
assert featanalysis.getClusterMaskFile(featdir, ci) == expect
else:
with pytest.raises(fslpath.PathError):
featanalysis.getClusterMaskFile(featdir, ci)
featanalysis.getClusterMaskFile(featdir, ci)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment