Skip to content
Snippets Groups Projects
Commit fafbf849 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Bugfixes to transform.py ('x' variable overwriting transformation

matrix), LightBoxPanel (not passing displayCtx to LightBoxCanvas),
fslview_parseargs (using imageList.bounds instead of displayCtx.bounds),
ImageList (didn't remove bounds-related code), ImageDisplay (attempting
to offset transformation matrices for affine, when only supposed to do
it for id/pixdim)
parent db50ebe7
No related branches found
No related tags found
No related merge requests found
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
"""Classes for representing 3D/4D images and collections of said images.""" """Classes for representing 3D/4D images and collections of said images."""
import os import os
import sys
import logging import logging
import tempfile import tempfile
import collections import collections
...@@ -322,9 +321,7 @@ class ImageList(props.HasProperties): ...@@ -322,9 +321,7 @@ class ImageList(props.HasProperties):
"""Class representing a collection of images to be displayed together. """Class representing a collection of images to be displayed together.
Contains a :class:`props.properties_types.List` property containing Contains a :class:`props.properties_types.List` property containing
:class:`Image` objects, and some other properties on which listeners may :class:`Image` objects.
register themselves to be notified when the properties of the image
collection changes (e.g. image bounds).
An :class:`ImageList` object has a few wrapper methods around the An :class:`ImageList` object has a few wrapper methods around the
:attr:`images` property, allowing the :class:`ImageList` to be used :attr:`images` property, allowing the :class:`ImageList` to be used
...@@ -350,14 +347,6 @@ class ImageList(props.HasProperties): ...@@ -350,14 +347,6 @@ class ImageList(props.HasProperties):
self.images = images self.images = images
self.addListener(
'images',
self.__class__.__name__,
self._imageListChanged)
# initialise image bounds
self._imageListChanged()
# set the _lastDir attribute, # set the _lastDir attribute,
# used by the addImages method # used by the addImages method
if len(images) == 0: self._lastDir = os.getcwd() if len(images) == 0: self._lastDir = os.getcwd()
...@@ -423,55 +412,6 @@ class ImageList(props.HasProperties): ...@@ -423,55 +412,6 @@ class ImageList(props.HasProperties):
return True return True
def _imageListChanged(self, *a):
"""Called whenever an item is added or removed from the :attr:`images`
list. Registers listeners with the properties of each image, and
calls the :meth:`_updateImageBounds` method.
"""
for img in self.images:
# This may be called multiple times on each image,
# but it doesn't matter, as any listener which has
# previously been registered with an image will
# just be replaced by the new one here.
img.addListener(
'transform',
self.__class__.__name__,
self._updateImageBounds,
overwrite=True)
self._updateImageBounds()
def _updateImageBounds(self, *a):
"""Called whenever an item is added or removed from the
:attr:`images` list, or an image property changes. Updates
the :attr:`bounds` property.
"""
if len(self.images) == 0:
minBounds = [0.0, 0.0, 0.0]
maxBounds = [0.0, 0.0, 0.0]
else:
minBounds = 3 * [ sys.float_info.max]
maxBounds = 3 * [-sys.float_info.max]
for img in self.images:
for ax in range(3):
lo, hi = img.imageBounds(ax)
if lo < minBounds[ax]: minBounds[ax] = lo
if hi > maxBounds[ax]: maxBounds[ax] = hi
self.bounds[:] = [minBounds[0], maxBounds[0],
minBounds[1], maxBounds[1],
minBounds[2], maxBounds[2]]
# Wrappers around the images list property, allowing this # Wrappers around the images list property, allowing this
# ImageList object to be used as if it is actually a list. # ImageList object to be used as if it is actually a list.
def __len__( self): return self.images.__len__() def __len__( self): return self.images.__len__()
......
...@@ -325,9 +325,10 @@ class ImageDisplay(props.HasProperties): ...@@ -325,9 +325,10 @@ class ImageDisplay(props.HasProperties):
# for pixdim/identity transformations, we want the world # for pixdim/identity transformations, we want the world
# location (0, 0, 0) to map to voxel location (0, 0, 0) # location (0, 0, 0) to map to voxel location (0, 0, 0)
for i in range(3): if self.transform in ('id', 'pixdim'):
self.voxToDisplayMat[3, i] = pixdim[i] * 0.5 for i in range(3):
self.displayToVoxMat[3, i] = -0.5 self.voxToDisplayMat[3, i] = pixdim[i] * 0.5
self.displayToVoxMat[3, i] = -0.5
# When transform is changed to 'affine', enable interpolation # When transform is changed to 'affine', enable interpolation
# and, when changed to 'pixdim' or 'id', disable interpolation # and, when changed to 'pixdim' or 'id', disable interpolation
...@@ -483,7 +484,7 @@ class DisplayContext(props.HasProperties): ...@@ -483,7 +484,7 @@ class DisplayContext(props.HasProperties):
minBounds = 3 * [ sys.float_info.max] minBounds = 3 * [ sys.float_info.max]
maxBounds = 3 * [-sys.float_info.max] maxBounds = 3 * [-sys.float_info.max]
for img in self.images: for img in self._imageList.images:
display = img.getAttribute('display') display = img.getAttribute('display')
xform = display.voxToDisplayMat xform = display.voxToDisplayMat
......
...@@ -90,7 +90,8 @@ class LightBoxPanel(canvaspanel.CanvasPanel): ...@@ -90,7 +90,8 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
self._scrollbar = wx.ScrollBar(self, style=wx.SB_VERTICAL) self._scrollbar = wx.ScrollBar(self, style=wx.SB_VERTICAL)
self._lbCanvas = lightboxcanvas.LightBoxCanvas(self.getCanvasPanel(), self._lbCanvas = lightboxcanvas.LightBoxCanvas(self.getCanvasPanel(),
imageList) imageList,
displayCtx)
# My properties are the canvas properties # My properties are the canvas properties
self.bindProps('sliceSpacing', self._lbCanvas) self.bindProps('sliceSpacing', self._lbCanvas)
......
...@@ -255,9 +255,9 @@ def handleImageArgs(args): ...@@ -255,9 +255,9 @@ def handleImageArgs(args):
loc = imageList[0].voxToWorld([args.voxelloc])[0] loc = imageList[0].voxToWorld([args.voxelloc])[0]
else: else:
loc = [imageList.bounds.xlo + 0.5 * imageList.bounds.xlen, loc = [displayCtx.bounds.xlo + 0.5 * displayCtx.bounds.xlen,
imageList.bounds.ylo + 0.5 * imageList.bounds.ylen, displayCtx.bounds.ylo + 0.5 * displayCtx.bounds.ylen,
imageList.bounds.zlo + 0.5 * imageList.bounds.zlen] displayCtx.bounds.zlo + 0.5 * displayCtx.bounds.zlen]
displayCtx.location.xyz = loc displayCtx.location.xyz = loc
......
...@@ -19,7 +19,7 @@ def invert(x): ...@@ -19,7 +19,7 @@ def invert(x):
return linalg.inv(x) return linalg.inv(x)
def axisBounds(shape, x, axis): def axisBounds(shape, xform, axis):
"""Returns the (lo, hi) bounds of the specified axis.""" """Returns the (lo, hi) bounds of the specified axis."""
x, y, z = shape x, y, z = shape
...@@ -38,7 +38,7 @@ def axisBounds(shape, x, axis): ...@@ -38,7 +38,7 @@ def axisBounds(shape, x, axis):
points[6, :] = [x, y, -0.5] points[6, :] = [x, y, -0.5]
points[7, :] = [x, y, z] points[7, :] = [x, y, z]
tx = transform(points, x) tx = transform(points, xform)
lo = tx[:, axis].min() lo = tx[:, axis].min()
hi = tx[:, axis].max() hi = tx[:, axis].max()
...@@ -46,7 +46,7 @@ def axisBounds(shape, x, axis): ...@@ -46,7 +46,7 @@ def axisBounds(shape, x, axis):
return (lo, hi) return (lo, hi)
def axisLength(shape, x, axis): def axisLength(shape, xform, axis):
"""Return the length, in real world units, of the specified axis. """Return the length, in real world units, of the specified axis.
""" """
...@@ -54,13 +54,13 @@ def axisLength(shape, x, axis): ...@@ -54,13 +54,13 @@ def axisLength(shape, x, axis):
points[:] = [-0.5, -0.5, -0.5] points[:] = [-0.5, -0.5, -0.5]
points[1, axis] = shape[axis] - 0.5 points[1, axis] = shape[axis] - 0.5
tx = transform(points, x) tx = transform(points, xform)
# euclidean distance between each boundary point # euclidean distance between each boundary point
return sum((tx[0, :] - tx[1, :]) ** 2) ** 0.5 return sum((tx[0, :] - tx[1, :]) ** 2) ** 0.5
def transform(p, x, axes=None): def transform(p, xform, axes=None):
"""Transforms the given set of points ``p`` according to the given affine """Transforms the given set of points ``p`` according to the given affine
transformation ``x``. The transformed points are returned as a transformation ``x``. The transformed points are returned as a
:class:``numpy.float64`` array. :class:``numpy.float64`` array.
...@@ -73,9 +73,9 @@ def transform(p, x, axes=None): ...@@ -73,9 +73,9 @@ def transform(p, x, axes=None):
y = p[:, 1] y = p[:, 1]
z = p[:, 2] z = p[:, 2]
t[:, 0] = x * x[0, 0] + y * x[1, 0] + z * x[2, 0] + x[3, 0] t[:, 0] = x * xform[0, 0] + y * xform[1, 0] + z * xform[2, 0] + xform[3, 0]
t[:, 1] = x * x[0, 1] + y * x[1, 1] + z * x[2, 1] + x[3, 1] t[:, 1] = x * xform[0, 1] + y * xform[1, 1] + z * xform[2, 1] + xform[3, 1]
t[:, 2] = x * x[0, 2] + y * x[1, 2] + z * x[2, 2] + x[3, 2] t[:, 2] = x * xform[0, 2] + y * xform[1, 2] + z * xform[2, 2] + xform[3, 2]
if axes is None: axes = [0, 1, 2] if axes is None: axes = [0, 1, 2]
......
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