Skip to content
Snippets Groups Projects
Forked from FSL / fslpy
813 commits behind the upstream repository.
test_image_roi.py 3.88 KiB
#!/usr/bin/env python
#
# test_image_roi.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#

import pytest

import numpy as np

import fsl.data.image as fslimage
import fsl.utils.image.roi as roi


def test_roi():

    # inshape, bounds, expected outshape, expected affine offset
    tests = [
        # 3D image, 3D roi
        ([10, 10, 10],     [(0, 10), (0, 10), (0, 10)], [10, 10, 10],     [0, 0, 0]),
        ([10, 10, 10],     [(1, 10), (1, 10), (1, 10)], [ 9,  9,  9],     [1, 1, 1]),
        ([10, 10, 10],     [(1,  9), (1,  9), (1,  9)], [ 8,  8,  8],     [1, 1, 1]),
        ([10, 10, 10],     [(3,  5), (3,  5), (3,  5)], [ 2,  2,  2],     [3, 3, 3]),
        ([10, 10, 10],     [(4,  5), (4,  5), (4,  5)], [ 1,  1,  1],     [4, 4, 4]),

        # 4D image, 3D roi
        ([10, 10, 10, 10], [(0, 10), (0, 10), (0, 10)], [10, 10, 10, 10], [0, 0, 0]),
        ([10, 10, 10, 10], [(1, 10), (1, 10), (1, 10)], [ 9,  9,  9, 10], [1, 1, 1]),
        ([10, 10, 10, 10], [(1,  9), (1,  9), (1,  9)], [ 8,  8,  8, 10], [1, 1, 1]),
        ([10, 10, 10, 10], [(3,  5), (3,  5), (3,  5)], [ 2,  2,  2, 10], [3, 3, 3]),
        ([10, 10, 10, 10], [(4,  5), (4,  5), (4,  5)], [ 1,  1,  1, 10], [4, 4, 4]),

        # 4D image, 4D roi
        ([10, 10, 10, 10], [(0, 10), (0, 10), (0, 10), (0, 10)], [10, 10, 10, 10], [0, 0, 0]),
        ([10, 10, 10, 10], [(1, 10), (1, 10), (1, 10), (1, 10)], [ 9,  9,  9,  9], [1, 1, 1]),
        ([10, 10, 10, 10], [(1,  9), (1,  9), (1,  9), (1,  9)], [ 8,  8,  8,  8], [1, 1, 1]),
        ([10, 10, 10, 10], [(3,  5), (3,  5), (3,  5), (3,  5)], [ 2,  2,  2,  2], [3, 3, 3]),
        ([10, 10, 10, 10], [(4,  5), (4,  5), (4,  5), (4,  5)], [ 1,  1,  1],     [4, 4, 4]),

        # expanding FOV
        ([10, 10, 10], [(-5, 15), ( 0, 10), ( 0, 10)], [20, 10, 10], [-5,  0,  0]),
        ([10, 10, 10], [(-5, 15), (-5, 15), ( 0, 10)], [20, 20, 10], [-5, -5,  0]),
        ([10, 10, 10], [(-5, 15), (-5, 10), (-5, 15)], [20, 15, 20], [-5, -5, -5]),
        ([10, 10, 10], [(-5, 15), ( 3, 7),  ( 0, 10)], [20,  4, 10], [-5,  3,  0]),
    ]

    for inshape, bounds, outshape, offset in tests:
        data  = np.random.randint(1, 10, inshape)
        image = fslimage.Image(data, xform=np.eye(4))

        result = roi.roi(image, bounds)

        expaff        = np.eye(4)
        expaff[:3, 3] = offset

        assert np.all(list(result.shape) == list(outshape))
        assert np.all(np.isclose(result.voxToWorldMat, expaff))

        oldslc = []
        newslc = []

        for (lo, hi), oldlen in zip(bounds, inshape):
            oldslc.append(slice(max(lo, 0), min(hi, oldlen)))

        if len(oldslc) < len(inshape):
            for d in inshape[len(oldslc):]:
                oldslc.append(slice(0, d))

        for (lo, hi), slc in zip(bounds, oldslc):
            if lo < 0:    newlo = -lo
            else:         newlo =  0

            oldlen = slc.stop - slc.start

            newslc.append(slice(newlo, newlo + oldlen))

        if len(newslc) > len(outshape):
            newslc = newslc[:len(outshape)]

        assert np.all(data[tuple(oldslc)] == result.data[tuple(newslc)])

    # Error on:
    #  - not enough bounds
    #  - too many bounds
    #  - hi >= lo
    data  = np.random.randint(1, 10, (10, 10, 10))
    image = fslimage.Image(data, xform=np.eye(4))
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (0, 10), (0, 10), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(5, 5),  (0, 10), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(6, 5),  (0, 10), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (5,  5), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (6,  5), (0, 10)])
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (0, 10), (5,  5)])
    with pytest.raises(ValueError): roi.roi(image, [(0, 10), (0, 10), (6,  5)])