Commit 075910d3 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Mesh calculates nvertices in init. Mesh load/add vertices/vertexData methods

check data shape, and raise if bad.
parent 66eb47f4
...@@ -182,10 +182,7 @@ class FreesurferMesh(fslmesh.Mesh): ...@@ -182,10 +182,7 @@ class FreesurferMesh(fslmesh.Mesh):
read_metadata=True, read_metadata=True,
read_stamp=True) read_stamp=True)
vertices = vertices.reshape(self.vertices.shape) return self.addVertices(vertices, key, **kwargs)
self.addVertices(vertices, key, **kwargs)
return vertices
def loadVertexData(self, infile, key=None): def loadVertexData(self, infile, key=None):
...@@ -203,10 +200,10 @@ class FreesurferMesh(fslmesh.Mesh): ...@@ -203,10 +200,10 @@ class FreesurferMesh(fslmesh.Mesh):
isvannot = isVertexAnnotFile(infile) isvannot = isVertexAnnotFile(infile)
if not any((isvdata, isvlabel, isvannot)): if not any((isvdata, isvlabel, isvannot)):
return fslmesh.Mesh.loadVertexData(infile) return fslmesh.Mesh.loadVertexData(self, infile)
infile = op.abspath(infile) infile = op.abspath(infile)
nvertices = self.vertices.shape[0] nvertices = self.nvertices
if key is None: if key is None:
key = infile key = infile
...@@ -222,7 +219,7 @@ class FreesurferMesh(fslmesh.Mesh): ...@@ -222,7 +219,7 @@ class FreesurferMesh(fslmesh.Mesh):
elif isvannot: elif isvannot:
vdata, lut, names = vdata vdata, lut, names = vdata
self.addVertexData(key, vdata) vdata = self.addVertexData(key, vdata)
if isvannot: if isvannot:
self.__luts[key] = lut, names, lut self.__luts[key] = lut, names, lut
......
...@@ -123,10 +123,10 @@ class GiftiMesh(fslmesh.Mesh): ...@@ -123,10 +123,10 @@ class GiftiMesh(fslmesh.Mesh):
key = infile key = infile
surfimg, vertices, _ = loadGiftiMesh(infile) surfimg, vertices, _ = loadGiftiMesh(infile)
vertices = vertices.reshape(self.vertices.shape[0], 3)
self.addVertices(vertices, key, *args, **kwargs) vertices = self.addVertices(vertices, key, *args, **kwargs)
self.setMeta( infile, surfimg)
self.setMeta(infile, surfimg)
return vertices return vertices
...@@ -139,18 +139,16 @@ class GiftiMesh(fslmesh.Mesh): ...@@ -139,18 +139,16 @@ class GiftiMesh(fslmesh.Mesh):
a plain text file which contains vertex data. a plain text file which contains vertex data.
""" """
if not infile.endswith('.gii'):
return fslmesh.Mesh.loadVertexData(self, infile)
infile = op.abspath(infile) infile = op.abspath(infile)
if key is None: if key is None:
key = infile key = infile
if infile.endswith('.gii'): vdata = loadGiftiVertexData(infile)[1]
vdata = loadGiftiVertexData(infile)[1] return self.addVertexData(key, vdata)
self.addVertexData(key, vdata)
return vdata
else:
return fslmesh.Mesh.loadVertexData(self, infile, key)
def loadGiftiMesh(filename): def loadGiftiMesh(filename):
......
...@@ -59,6 +59,8 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -59,6 +59,8 @@ class Mesh(notifier.Notifier, meta.Meta):
``dataSource`` Full path to the mesh file (or ``None`` if there is ``dataSource`` Full path to the mesh file (or ``None`` if there is
no file associated with this mesh). no file associated with this mesh).
``nvertices`` The number of vertices in the mesh.
``vertices`` A ``(n, 3)`` array containing the currently selected ``vertices`` A ``(n, 3)`` array containing the currently selected
vertices. You can assign a vertex set key to this vertices. You can assign a vertex set key to this
attribute to change the selected vertex set. attribute to change the selected vertex set.
...@@ -185,6 +187,7 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -185,6 +187,7 @@ class Mesh(notifier.Notifier, meta.Meta):
self.__name = name self.__name = name
self.__dataSource = dataSource self.__dataSource = dataSource
self.__indices = np.asarray(indices).reshape((-1, 3)) self.__indices = np.asarray(indices).reshape((-1, 3))
self.__nvertices = self.__indices.max() + 1
# This attribute is used to store # This attribute is used to store
# the currently selected vertex set, # the currently selected vertex set,
...@@ -247,6 +250,12 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -247,6 +250,12 @@ class Mesh(notifier.Notifier, meta.Meta):
return self.__dataSource return self.__dataSource
@property
def nvertices(self):
"""Returns the number of vertices in the mesh. """
return self.__nvertices
@property @property
def vertices(self): def vertices(self):
"""The ``(N, 3)`` vertices of this mesh. """ """The ``(N, 3)`` vertices of this mesh. """
...@@ -352,11 +361,8 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -352,11 +361,8 @@ class Mesh(notifier.Notifier, meta.Meta):
key = infile key = infile
vertices = np.loadtxt(infile) vertices = np.loadtxt(infile)
vertices = vertices.reshape(self.vertices.shape)
self.addVertices(vertices, key, **kwargs) return self.addVertices(vertices, key, **kwargs)
return vertices
def addVertices(self, vertices, key=None, select=True, fixWinding=False): def addVertices(self, vertices, key=None, select=True, fixWinding=False):
...@@ -374,6 +380,11 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -374,6 +380,11 @@ class Mesh(notifier.Notifier, meta.Meta):
:arg fixWinding: Defaults to ``False``. If ``True``, the vertex :arg fixWinding: Defaults to ``False``. If ``True``, the vertex
winding order of every triangle is is fixed so they winding order of every triangle is is fixed so they
all have outward-facing normal vectors. all have outward-facing normal vectors.
:returns: The vertices, possibly reshaped
:raises: ``ValueError`` if the provided ``vertices`` array
has the wrong number of vertices.
""" """
if key is None: if key is None:
...@@ -383,6 +394,19 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -383,6 +394,19 @@ class Mesh(notifier.Notifier, meta.Meta):
lo = vertices.min(axis=0) lo = vertices.min(axis=0)
hi = vertices.max(axis=0) hi = vertices.max(axis=0)
# Don't allow vertices of
# different size to be added
try:
vertices = vertices.reshape(self.nvertices, 3)
# reshape raised an error -
# wrong number of vertices
except ValueError:
raise ValueError('{}: invalid number of vertices: '
'{} != ({}, 3)'.format(key,
vertices.shape,
self.nvertices))
self.__vertices[key] = vertices self.__vertices[key] = vertices
self.__loBounds[key] = lo self.__loBounds[key] = lo
self.__hiBounds[key] = hi self.__hiBounds[key] = hi
...@@ -405,6 +429,8 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -405,6 +429,8 @@ class Mesh(notifier.Notifier, meta.Meta):
for k, fn in self.__faceNormals.items(): for k, fn in self.__faceNormals.items():
self.__faceNormals[k] = fn * -1 self.__faceNormals[k] = fn * -1
return vertices
def vertexSets(self): def vertexSets(self):
"""Returns a list containing the keys of all vertex sets. """ """Returns a list containing the keys of all vertex sets. """
...@@ -435,27 +461,28 @@ class Mesh(notifier.Notifier, meta.Meta): ...@@ -435,27 +461,28 @@ class Mesh(notifier.Notifier, meta.Meta):
if key is None: if key is None:
key = infile key = infile
nvertices = self.vertices.shape[0]
vertexData = np.loadtxt(infile) vertexData = np.loadtxt(infile)
vertexData = vertexData.reshape(nvertices, -1)
self.addVertexData(key, vertexData) return self.addVertexData(key, vertexData)
return vertexData
def addVertexData(self, key, vdata): def addVertexData(self, key, vdata):
"""Adds a vertex-wise data set to the ``Mesh``. It can be retrieved """Adds a vertex-wise data set to the ``Mesh``. It can be retrieved
by passing the specified ``key`` to the :meth:`getVertexData` method. by passing the specified ``key`` to the :meth:`getVertexData` method.
:returns: The vertex data, possibly reshaped.
""" """
nvertices = self.vertices.shape[0] nvertices = self.nvertices
if vdata.ndim not in (1, 2) or vdata.shape[0] != nvertices: if vdata.ndim not in (1, 2) or vdata.shape[0] != nvertices:
raise ValueError('{}: incompatible vertex data ' raise ValueError('{}: incompatible vertex data '
'shape: {}'.format(key, vdata.shape)) 'shape: {}'.format(key, vdata.shape))
self.__vertexData[key] = vdata.reshape(nvertices, -1) vdata = vdata.reshape(nvertices, -1)
self.__vertexData[key] = vdata
return vdata
def getVertexData(self, key): def getVertexData(self, key):
......
Supports Markdown
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