Commit 60f6e154 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'bf/mesh' into 'master'

Bf/mesh

See merge request fsl/fslpy!288
parents 3c57660e 71e2cada
...@@ -31,6 +31,13 @@ Deprecated ...@@ -31,6 +31,13 @@ Deprecated
library on [PyPI](https://pypi.org/project/file-tree/). library on [PyPI](https://pypi.org/project/file-tree/).
Fixed
^^^^^
* Fixed an edge-case in the :mod:`.gifti` module, where a surface with a
single triangle was being loaded incorrectly.
3.5.3 (Tuesday 9th February 2021) 3.5.3 (Tuesday 9th February 2021)
--------------------------------- ---------------------------------
......
...@@ -229,7 +229,7 @@ def loadGiftiMesh(filename): ...@@ -229,7 +229,7 @@ def loadGiftiMesh(filename):
'at least one pointset array'.format(filename)) 'at least one pointset array'.format(filename))
vertices = [ps.data for ps in pointsets] vertices = [ps.data for ps in pointsets]
indices = triangles[0].data indices = np.atleast_2d(triangles[0].data)
if len(vdata) == 0: vdata = None if len(vdata) == 0: vdata = None
else: vdata = prepareGiftiVertexData(vdata, filename) else: vdata = prepareGiftiVertexData(vdata, filename)
......
...@@ -573,7 +573,7 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -573,7 +573,7 @@ class Mesh(notifier.Notifier, meta.Meta):
# sort by ray. I'm Not sure if this is # sort by ray. I'm Not sure if this is
# needed - does trimesh do it for us? # needed - does trimesh do it for us?
rayIdxs = np.asarray(np.argsort(rays), np.int) rayIdxs = np.asarray(np.argsort(rays))
locs = locs[rayIdxs] locs = locs[rayIdxs]
tris = tris[rayIdxs] tris = tris[rayIdxs]
...@@ -687,7 +687,7 @@ def calcFaceNormals(vertices, indices): ...@@ -687,7 +687,7 @@ def calcFaceNormals(vertices, indices):
fnormals = np.cross((v1 - v0), (v2 - v0)) fnormals = np.cross((v1 - v0), (v2 - v0))
fnormals = affine.normalise(fnormals) fnormals = affine.normalise(fnormals)
return fnormals return np.atleast_2d(fnormals)
def calcVertexNormals(vertices, indices, fnormals): def calcVertexNormals(vertices, indices, fnormals):
......
...@@ -280,7 +280,7 @@ class DeformationField(NonLinearTransform): ...@@ -280,7 +280,7 @@ class DeformationField(NonLinearTransform):
# Mask out the coordinates # Mask out the coordinates
# that are out of bounds of # that are out of bounds of
# the deformation field # the deformation field
voxels = np.round(voxels).astype(np.int) voxels = np.round(voxels).astype(np.int32)
voxmask = (voxels >= [0, 0, 0]) & (voxels < self.shape[:3]) voxmask = (voxels >= [0, 0, 0]) & (voxels < self.shape[:3])
voxmask = voxmask.all(axis=1) voxmask = voxmask.all(axis=1)
voxels = voxels[voxmask] voxels = voxels[voxmask]
...@@ -508,9 +508,9 @@ class CoefficientField(NonLinearTransform): ...@@ -508,9 +508,9 @@ class CoefficientField(NonLinearTransform):
u = np.remainder(i, 1) u = np.remainder(i, 1)
v = np.remainder(j, 1) v = np.remainder(j, 1)
w = np.remainder(k, 1) w = np.remainder(k, 1)
i = np.floor(i).astype(np.int) i = np.floor(i).astype(np.int32)
j = np.floor(j).astype(np.int) j = np.floor(j).astype(np.int32)
k = np.floor(k).astype(np.int) k = np.floor(k).astype(np.int32)
disps = np.zeros(coords.shape) disps = np.zeros(coords.shape)
......
...@@ -85,7 +85,7 @@ def _get_zero_mask(aimg): ...@@ -85,7 +85,7 @@ def _get_zero_mask(aimg):
elif isinstance(aimg, fslatlases.ProbabilisticAtlas): elif isinstance(aimg, fslatlases.ProbabilisticAtlas):
# Keep memory usage down # Keep memory usage down
zmask = np.ones(aimg.shape[:3], dtype=np.bool) zmask = np.ones(aimg.shape[:3], dtype=bool)
for vol in range(aimg.shape[-1]): for vol in range(aimg.shape[-1]):
zmask = np.logical_and(zmask, aimg[..., vol] == 0) zmask = np.logical_and(zmask, aimg[..., vol] == 0)
......
...@@ -381,3 +381,21 @@ def test_GiftiMesh_needsFixing(): ...@@ -381,3 +381,21 @@ def test_GiftiMesh_needsFixing():
surf = gifti.GiftiMesh(fname, fixWinding=True) surf = gifti.GiftiMesh(fname, fixWinding=True)
assert np.all(np.isclose(surf.indices, idxs_fixed)) assert np.all(np.isclose(surf.indices, idxs_fixed))
def test_loadGiftiMesh_onetriangle():
verts = np.array([[0, 0, 0], [1, 1, 1], [0, 1, 0]])
idxs = np.array([[0, 1, 2]])
verts = nib.gifti.GiftiDataArray(verts, intent='NIFTI_INTENT_POINTSET')
idxs = nib.gifti.GiftiDataArray(idxs, intent='NIFTI_INTENT_TRIANGLE')
gimg = nib.gifti.GiftiImage(darrays=[verts, idxs])
with tempdir():
fname = op.abspath('test.gii')
gimg.to_filename(fname)
gimg, tris, verts, _ = gifti.loadGiftiMesh('test.gii')
verts = verts[0]
assert verts.shape == (3, 3)
assert tris.shape == (1, 3)
...@@ -75,7 +75,7 @@ def test_resample(seed): ...@@ -75,7 +75,7 @@ def test_resample(seed):
(np.isclose(np.modf(origtestcoords)[0], 0.5))) (np.isclose(np.modf(origtestcoords)[0], 0.5)))
out = np.any(out, axis=1) | (resvals == 0) out = np.any(out, axis=1) | (resvals == 0)
origtestcoords = np.array(origtestcoords.round(), dtype=np.int) origtestcoords = np.array(origtestcoords.round(), dtype=int)
origtestcoords = origtestcoords[~out, :] origtestcoords = origtestcoords[~out, :]
restestcoords = restestcoords[ ~out, :] restestcoords = restestcoords[ ~out, :]
...@@ -166,8 +166,8 @@ def test_resampleToPixdims(): ...@@ -166,8 +166,8 @@ def test_resampleToPixdims():
img = fslimage.Image(make_random_image(dims=(10, 10, 10))) img = fslimage.Image(make_random_image(dims=(10, 10, 10)))
imglo, imghi = affine.axisBounds(img.shape, img.voxToWorldMat) imglo, imghi = affine.axisBounds(img.shape, img.voxToWorldMat)
oldpix = np.array(img.pixdim, dtype=np.float) oldpix = np.array(img.pixdim, dtype=float)
oldshape = np.array(img.shape, dtype=np.float) oldshape = np.array(img.shape, dtype=float)
for i, origin in it.product(range(25), ('centre', 'corner')): for i, origin in it.product(range(25), ('centre', 'corner')):
...@@ -215,16 +215,16 @@ def test_resampleToReference2(): ...@@ -215,16 +215,16 @@ def test_resampleToReference2():
# More specific test - output # More specific test - output
# data gets transformed correctly # data gets transformed correctly
# into reference space # into reference space
img = np.zeros((5, 5, 5), dtype=np.float) img = np.zeros((5, 5, 5), dtype=float)
img[1, 1, 1] = 1 img[1, 1, 1] = 1
img = fslimage.Image(img) img = fslimage.Image(img)
refv2w = affine.scaleOffsetXform([1, 1, 1], [-1, -1, -1]) refv2w = affine.scaleOffsetXform([1, 1, 1], [-1, -1, -1])
ref = np.zeros((5, 5, 5), dtype=np.float) ref = np.zeros((5, 5, 5), dtype=float)
ref = fslimage.Image(ref, xform=refv2w) ref = fslimage.Image(ref, xform=refv2w)
res = resample.resampleToReference(img, ref, order=0) res = resample.resampleToReference(img, ref, order=0)
exp = np.zeros((5, 5, 5), dtype=np.float) exp = np.zeros((5, 5, 5), dtype=float)
exp[2, 2, 2] = 1 exp[2, 2, 2] = 1
assert np.all(np.isclose(res[0], exp)) assert np.all(np.isclose(res[0], exp))
......
...@@ -1195,7 +1195,7 @@ def test_3D_indexing(shape=None, img=None): ...@@ -1195,7 +1195,7 @@ def test_3D_indexing(shape=None, img=None):
assert type(img[0, 0, 0]) == np.float64 assert type(img[0, 0, 0]) == np.float64
mask1 = np.zeros(shape, dtype=np.bool) mask1 = np.zeros(shape, dtype=bool)
mask1[0, 0, 0] = True mask1[0, 0, 0] = True
mask1[1, 0, 0] = True mask1[1, 0, 0] = True
...@@ -1252,7 +1252,7 @@ def test_3D_4D_indexing(): ...@@ -1252,7 +1252,7 @@ def test_3D_4D_indexing():
assert type(img[0, 0, 0, 0]) == np.float64 assert type(img[0, 0, 0, 0]) == np.float64
assert type(img[0, 0, 0, :]) == np.float64 assert type(img[0, 0, 0, :]) == np.float64
mask = np.zeros(padShape, dtype=np.bool) mask = np.zeros(padShape, dtype=bool)
mask[0, 0, 0, 0] = True mask[0, 0, 0, 0] = True
assert type(img[mask]) == np.ndarray assert type(img[mask]) == np.ndarray
...@@ -1282,13 +1282,13 @@ def test_3D_len_one_indexing(shape=None, img=None): ...@@ -1282,13 +1282,13 @@ def test_3D_len_one_indexing(shape=None, img=None):
assert type(img[0, 0]) == np.ndarray assert type(img[0, 0]) == np.ndarray
assert type(img[0, 0, 0]) == np.float64 assert type(img[0, 0, 0]) == np.float64
mask = np.zeros(shape[:2], dtype=np.bool) mask = np.zeros(shape[:2], dtype=bool)
mask[0, 0] = True mask[0, 0] = True
assert type(img[mask]) == np.ndarray assert type(img[mask]) == np.ndarray
assert img[mask].shape == (1, ) assert img[mask].shape == (1, )
mask = np.zeros(shape, dtype=np.bool) mask = np.zeros(shape, dtype=bool)
mask[0, 0, 0] = True mask[0, 0, 0] = True
assert type(img[mask]) == np.ndarray assert type(img[mask]) == np.ndarray
...@@ -1352,7 +1352,7 @@ def test_4D_indexing(shape=None, img=None): ...@@ -1352,7 +1352,7 @@ def test_4D_indexing(shape=None, img=None):
assert type(img[0, 0, 0, 0]) == np.float64 assert type(img[0, 0, 0, 0]) == np.float64
mask1 = np.zeros(shape, dtype=np.bool) mask1 = np.zeros(shape, dtype=bool)
mask1[0, 0, 0, 0] = True mask1[0, 0, 0, 0] = True
mask1[1, 0, 0, 0] = True mask1[1, 0, 0, 0] = True
......
...@@ -234,6 +234,13 @@ def test_normals(): ...@@ -234,6 +234,13 @@ def test_normals():
-fnormals, fslmesh.calcFaceNormals(verts, triangles_cw))) -fnormals, fslmesh.calcFaceNormals(verts, triangles_cw)))
assert np.all(np.isclose( assert np.all(np.isclose(
fnormals, fslmesh.calcFaceNormals(verts, triangles_ccw))) fnormals, fslmesh.calcFaceNormals(verts, triangles_ccw)))
# Make sure result is (1, 3) for input of (1, 3)
onetri = np.atleast_2d(triangles_ccw[0, :])
result = fslmesh.calcFaceNormals(verts, onetri)
assert result.shape == (1, 3)
assert np.all(np.isclose(fnormals[0, :], result))
assert np.all(np.isclose( assert np.all(np.isclose(
-vnormals, fslmesh.calcVertexNormals(verts, triangles_cw, -fnormals))) -vnormals, fslmesh.calcVertexNormals(verts, triangles_cw, -fnormals)))
assert np.all(np.isclose( assert np.all(np.isclose(
......
...@@ -395,7 +395,7 @@ def test_transform(): ...@@ -395,7 +395,7 @@ def test_transform():
mask = np.array([[1, 0, 0, 1], mask = np.array([[1, 0, 0, 1],
[0, 1, 0, 1], [0, 1, 0, 1],
[0, 0, 1, 1], [0, 0, 1, 1],
[0, 0, 0, 1]], dtype=np.bool) [0, 0, 0, 1]], dtype=bool)
return np.all((xform != 0) == mask) return np.all((xform != 0) == mask)
......
...@@ -161,7 +161,7 @@ def test_convertDeformationSpace(): ...@@ -161,7 +161,7 @@ def test_convertDeformationSpace():
refcoords = [np.random.randint(0, basefield.shape[0], 5), refcoords = [np.random.randint(0, basefield.shape[0], 5),
np.random.randint(0, basefield.shape[1], 5), np.random.randint(0, basefield.shape[1], 5),
np.random.randint(0, basefield.shape[2], 5)] np.random.randint(0, basefield.shape[2], 5)]
refcoords = np.array(refcoords, dtype=np.int).T refcoords = np.array(refcoords, dtype=int).T
refcoords = affine.transform(refcoords, ref.voxToScaledVoxMat) refcoords = affine.transform(refcoords, ref.voxToScaledVoxMat)
srccoords = basefield.transform(refcoords) srccoords = basefield.transform(refcoords)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment