diff --git a/fsl.py b/fsl.py index 7b7f3a5e2c563b90bd1b6af1a24ac4aa760d25de..b0854b773a75931f4283a30c29358f16b6bebaa9 100755 --- a/fsl.py +++ b/fsl.py @@ -151,15 +151,15 @@ def buildGUI(fslTool, toolCtx, fslEnvActive): actions.append(( wx.ID_HELP, '{} Help'.format(fslTool.toolName), - lambda ev: webpage.openFSLHelp(fslTool.helpPage))) + lambda *ev: webpage.openFSLHelp(fslTool.helpPage))) for (name, func) in fslTool.actions: - actions.append((-1, name, lambda ev: func(frame, ctx))) + actions.append((wx.ID_ANY, name, lambda ev, f=func: f(frame, ctx))) actions.append(( wx.ID_EXIT, 'Exit', - lambda ev: frame.Close())) + lambda *ev: frame.Close())) for wxId, name, func in actions: menuItem = fslMenu.Append(wxId, name) diff --git a/fsl/data/fslimage.py b/fsl/data/fslimage.py index 3828be36b40ea38407d089ac0746d295316e7069..45d000ec99876d160875a7c7b64cfa19dc4b7a24 100644 --- a/fsl/data/fslimage.py +++ b/fsl/data/fslimage.py @@ -77,8 +77,8 @@ class Image(object): lo, hi = sorted(tx[:, axis]) - lo = lo - self.pixdim[axis] * 0.5 - hi = hi + self.pixdim[axis] * 0.5 + lo = float(lo - self.pixdim[axis] * 0.5) + hi = float(hi + self.pixdim[axis] * 0.5) return (lo, hi) @@ -87,7 +87,9 @@ class Image(object): """ Transforms the given set of points in voxel coordinates to points in world coordinates, according to the affine - transformation specified in the image file. Parameters: + transformation specified in the image file. The returned array + is either a numpy.float64 array, or a single integer value, + depending on the input. Parameters: - p: N*A array, where N is the number of points, and A is the number of axes to consider (default: 3) @@ -101,31 +103,39 @@ class Image(object): """ voxp = self._transform(p, self.worldToVoxMat, axes) - voxp = np.array(voxp, dtype=np.int64) - - return voxp + + if voxp.size == 1: return int(voxp[0]) + else: return voxp def voxToWorld(self, p, axes=None): """ Transforms the given set of points in world coordinates to points in voxel coordinates, according to the affine - transformation specified in the image file. See the - worldToVox docstring for more details. - - """ - return self._transform(p, self.voxToWorldMat, axes) + transformation specified in the image file. The returned + array is either a numpy.float64 array, or a single float + value, depending on the input. See the worldToVox + docstring for more details. + """ + + worldp = self._transform(p, self.voxToWorldMat, axes) + + if worldp.size == 1: + #print 'casting to float!' + return float(worldp) + else: return worldp def _transform(self, p, a, axes): """ Transforms the given set of points p according to the given - affine transformation a. See the worldToVox docstring for - more details. + affine transformation a. The transformed points are returned + as a numpy.float64 array. See the worldToVox docstring for + more details. """ p = self._fillPoints(p, axes) - t = np.zeros((len(p), 3), dtype=p.dtype) + t = np.zeros((len(p), 3), dtype=np.float64) x = p[:, 0] y = p[:, 1] @@ -148,6 +158,7 @@ class Image(object): """ if not isinstance(p, collections.Iterable): p = [p] + p = np.array(p) if axes is None: return p diff --git a/fsl/fslview/imagelistpanel.py b/fsl/fslview/imagelistpanel.py index 389bd00835a2c372f9f22212d8301f6c391235c6..ca1d53b092eac426b9a3ec3e5f1534bd033dcf5c 100644 --- a/fsl/fslview/imagelistpanel.py +++ b/fsl/fslview/imagelistpanel.py @@ -112,11 +112,12 @@ class ImageListPanel(wx.Panel): except: lastDir = os.getcwd() wildcard = imagefile.wildcard() - + + # wx wildcard handling is buggy, so i'm disabling it for now dlg = wx.FileDialog(self.GetParent(), message='Open image file', defaultDir=lastDir, - wildcard=wildcard, +# wildcard=wildcard, style=wx.FD_OPEN) if dlg.ShowModal() != wx.ID_OK: return diff --git a/fsl/fslview/orthopanel.py b/fsl/fslview/orthopanel.py index 0c774506846048b1d40870ac0574904eea610e2b..de806cd8620d751800330c23aeb4ffbc50b26298 100644 --- a/fsl/fslview/orthopanel.py +++ b/fsl/fslview/orthopanel.py @@ -152,3 +152,16 @@ class OrthoFrame(wx.Frame): wx.Frame.__init__(self, parent, title=title) self.panel = OrthoPanel(self, imageList) self.Layout() + + +class OrthoDialog(wx.Dialog): + """ + Convenience class for displaying an OrthoPanel in a (possibly modal) + dialog window. + """ + + def __init__(self, parent, imageList, title=None): + + wx.Dialog.__init__(self, parent, title=title) + self.panel = OrthoPanel(self, imageList) + self.Layout() diff --git a/fsl/fslview/slicecanvas.py b/fsl/fslview/slicecanvas.py index 5071bbde76093f56c070841e1c165c4c148b3d6d..05e60d3570d3713554cb6d3483d0c77fbe2aa2af 100644 --- a/fsl/fslview/slicecanvas.py +++ b/fsl/fslview/slicecanvas.py @@ -120,17 +120,20 @@ class GLImageData(object): yidxs = np.arange(self.ydim, dtype=np.float32) yidxs, xidxs = np.meshgrid(yidxs, xidxs, indexing='ij') - # And put them into a single array (the image.voxToWorld - # method needs xyz coordinates, hence the N*3 shape here) - positionData = np.zeros((self.xdim * self.ydim, 3), dtype=np.float32) - positionData[:, xax] = xidxs.ravel(order='C') - positionData[:, yax] = yidxs.ravel(order='C') + # And put them into a single array + positionData = np.vstack(( + xidxs.ravel(order='C'), + yidxs.ravel(order='C'))).transpose() # Then we transform them from voxel - # coordinates to world coordinates - positionData = image.voxToWorld(positionData)[:, (xax, yax)] - - # GL buffers for the geometry and position data + # coordinates to world coordinates, + # making sure that they are of type + # float32 + positionData = image.voxToWorld(positionData, axes=(xax, yax)) + positionData = np.array(positionData, dtype=np.float32) + + # Define GL buffers for the geometry and position + # data containing the data we just created above geomData = geomData .ravel(order='C') positionData = positionData.ravel(order='C') geomBuffer = vbo.VBO(geomData, gl.GL_STATIC_DRAW) @@ -461,6 +464,13 @@ class SliceCanvas(wxgl.GLCanvas): self._ypos = None self._zpos = None + self.xmin = 0 + self.ymin = 0 + self.zmin = 0 + self.xmax = 1 + self.ymax = 1 + self.zmax = 1 + # This flag is set by the _initGLData method # when it has finished initialising the OpenGL # shaders diff --git a/fsl/tools/bet.py b/fsl/tools/bet.py index 39dc18f89960d823f14b62693c6228c08a501cd2..849379a63f809760b2ec325b0bf83e7a058f84d3 100644 --- a/fsl/tools/bet.py +++ b/fsl/tools/bet.py @@ -140,7 +140,7 @@ class Options(props.HasProperties): cmd.append('-r') cmd.append('{}'.format(self.headRadius)) - if all((self.xCoordinate > 0.0, + if any((self.xCoordinate > 0.0, self.yCoordinate > 0.0, self.zCoordinate > 0.0)): cmd.append('-c') @@ -193,40 +193,11 @@ def selectHeadCentre(opts, button): image = fslimage.Image(opts.inputImage) imageList = fslimage.ImageList([image]) parent = button.GetTopLevelParent() - frame = orthopanel.OrthoFrame(parent, imageList, opts.inputImage) + frame = orthopanel.OrthoDialog(parent, imageList, opts.inputImage) panel = frame.panel - voxCoords = [opts.xCoordinate, opts.yCoordinate, opts.zCoordinate] - worldCoords = image.voxToWorld([voxCoords])[0] - - panel.setLocation(*worldCoords) - # Whenever the x/y/z coordinates change on - # the Options object,update the orthopanel - # location - def updateViewX(val, *a): panel.setXLocation(image.voxToWorld(val, axes=0)) - def updateViewY(val, *a): panel.setYLocation(image.voxToWorld(val, axes=1)) - def updateViewZ(val, *a): panel.setZLocation(image.voxToWorld(val, axes=2)) - - optListeners = ( - ('xCoordinate', 'updateViewX_{}'.format(id(panel)), updateViewX), - ('yCoordinate', 'updateViewY_{}'.format(id(panel)), updateViewY), - ('zCoordinate', 'updateViewZ_{}'.format(id(panel)), updateViewZ)) - - for listener in optListeners: - opts.addListener(*listener) - - def rmListeners(ev): - for listener in optListeners: - prop = listener[0] - name = listener[1] - opts.removeListener(prop, name) - - # Remove the listeners when the dialog is closed - frame.Bind(wx.EVT_WINDOW_DESTROY, rmListeners) - - # And whenever the x/y/z coordinates change - # on the dialog, update the option values. + # the ortho panel, update the option values. def updateOpts(ev): x = image.worldToVox(ev.x, axes=0) y = image.worldToVox(ev.y, axes=1) @@ -247,10 +218,18 @@ def selectHeadCentre(opts, button): panel.Bind(orthopanel.EVT_LOCATION_EVENT, updateOpts) + # Set the initial location on the orthopanel. + # TODO this ain't working, as it needs to be + # done after the frame has been displayed, i.e + # via wx.CallAfter or similar. + voxCoords = [opts.xCoordinate, opts.yCoordinate, opts.zCoordinate] + worldCoords = image.voxToWorld([voxCoords])[0] + panel.setLocation(*worldCoords) + # Position the dialog by the button that was clicked pos = button.GetScreenPosition() frame.SetPosition(pos) - frame.Show() + frame.ShowModal() betView = props.NotebookGroup(( @@ -297,10 +276,15 @@ def runBet(parent, opts): if exitCode != 0: return - image = nb.load(imagefile.addExt(opts.outputImage)) - frame = orthopanel.OrthoFrame(window, - image.get_data(), - title=opts.outputImage) + inImage = fslimage.Image(opts.inputImage) + outImage = fslimage.Image(opts.outputImage) + imageList = fslimage.ImageList([inImage, outImage]) + + outImage.display.cmap = 'Reds' + outImage.display.displayMin = 1 + outImage.display.rangeClip = True + + frame = orthopanel.OrthoFrame(parent, imageList, opts.outputImage) frame.Show() runwindow.checkAndRun('BET', opts, parent, Options.genBetCmd, diff --git a/fsl/tools/fslview.py b/fsl/tools/fslview.py index c5b9cd167511525f5e7da6ca8bae2fe390456ff2..11fd296ba8fc03d1bed1dbd6e1b0901a4ec79e41 100644 --- a/fsl/tools/fslview.py +++ b/fsl/tools/fslview.py @@ -30,6 +30,7 @@ class FslViewPanel(wx.Panel): self.sizer.Add(self.listPanel, flag=wx.EXPAND) self.Layout() + self.Fit() def fslviewArguments(parser):