From 593e70e58ea7551e57e817ddb08d70c34673bb04 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Tue, 23 Jun 2015 17:27:41 +0100 Subject: [PATCH] Load lut feature is working. Simplified colour map/lut installation code - I'm still not entirely happy with any of this code. --- fsl/data/strings.py | 1 + fsl/fslview/colourmaps.py | 88 ++++++++++-------------- fsl/fslview/controls/lookuptablepanel.py | 43 ++++++++---- 3 files changed, 65 insertions(+), 67 deletions(-) diff --git a/fsl/data/strings.py b/fsl/data/strings.py index c933d5210..b1f07c015 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -116,6 +116,7 @@ titles = TypeDict({ 'LutLabelDialog' : 'New LUT label', 'NewLutDialog' : 'New LUT', + 'LookupTablePanel.loadLut' : 'Select a lookup table file', 'LookupTablePanel.labelExists' : 'Label already exists', }) diff --git a/fsl/fslview/colourmaps.py b/fsl/fslview/colourmaps.py index 6bc98900e..fcf3a7c37 100644 --- a/fsl/fslview/colourmaps.py +++ b/fsl/fslview/colourmaps.py @@ -133,7 +133,6 @@ and generating/manipulating colours.: import logging import glob -import shutil import bisect import os.path as op @@ -250,8 +249,6 @@ class LutLabel(object): class LookupTable(props.HasProperties): """Class which encapsulates a list of labels and associated colours and names, defining a lookup table to be used for colouring label images. - - :attr:`lutFile` """ @@ -274,12 +271,10 @@ class LookupTable(props.HasProperties): def __init__(self, name, lutFile=None): - self.name = name - self.lutFile = lutFile + self.name = name if lutFile is not None: self._load(lutFile) - self.saved = True def __len__(self): @@ -385,20 +380,10 @@ class LookupTable(props.HasProperties): self.set(label, name=lName, colour=(r, g, b), enabled=True) - def save(self, lutFile=None): + def _save(self, lutFile): """Saves this ``LookupTable`` instance to the specified ``lutFile``. - - If ``lutFile`` is not provided, saves the lut information to the - ``lutFile`` specified in :meth:`__init__`, or on a previous call to - this method. """ - if lutFile is None: - lutFile = self.lutFile - - if lutFile is None: - raise ValueError('No lookup table file specified') - with open(lutFile, 'wt') as f: for label in self.labels: value = label.value() @@ -410,9 +395,6 @@ class LookupTable(props.HasProperties): f.write('{}\n'.format(line)) - self.lutFile = lutFile - self.saved = True - def init(): """This function must be called before any of the other functions in this @@ -522,7 +504,7 @@ def registerColourMap(cmapFile, overlayList=None, displayCtx=None, name=None): mplcm.register_cmap(name, cmap) - _cmaps[name] = _Map(name, cmap, cmapFile, False) + _cmaps[name] = _Map(name, cmap, None, False) # TODO Any new Opts types which have a colour # map will need to be patched here @@ -586,8 +568,14 @@ def registerLookupTable(lut, overlayList=None, displayCtx=None, name=None): else: if name is None: name = lut.name + else: + lut.name = name + + # Even though the lut may have been loaded from + # a file, it has not necessarily been installed + lut.saved = False - _luts[name] = _Map(name, lut, lutFile, False) + _luts[name] = _Map(name, lut, None, False) log.debug('Patching LabelOpts classes to support ' 'new LookupTable {}'.format(name)) @@ -607,6 +595,8 @@ def registerLookupTable(lut, overlayList=None, displayCtx=None, name=None): # and for any future label overlays fsldisplay.LabelOpts.lut.addChoice(lut, lut.name) + + return lut def getLookupTables(): @@ -651,36 +641,24 @@ def isLookupTableInstalled(lutName): def installColourMap(cmapName): """Attempts to install a previously registered colourmap into the ``fsl/fslview/colourmaps`` directory. - - A ``KeyError`` is raised if the colourmap is not registered, a - ``RuntimeError`` if the colourmap cannot be installed, or an - ``IOError`` if the colourmap file cannot be copied. """ # keyerror if not registered cmap = _cmaps[cmapName] - # built-in, or already installed - if cmap.installed: - return - - # cmap has been incorrectly registered - if cmap.mapFile is None: - raise RuntimeError('Colour map {} appears to have been ' - 'incorrectly registered'.format(cmapName)) - - destfile = op.join(op.dirname(__file__), - 'colourmaps', - '{}.cmap'.format(cmapName)) + if cmap.mapFile is not None: + destFile = cmap.mapFile + else: + destFile = op.join(op.dirname(__file__), + 'colourmaps', + '{}.cmap'.format(cmapName)) - # destination file already exists - if op.exists(destfile): - raise RuntimeError('Destination file for colour map {} already ' - 'exists: {}'.format(cmapName, destfile)) + log.debug('Installing colour map {} to {}'.format(cmapName, destFile)) - log.debug('Installing colour map {} to {}'.format(cmapName, destfile)) - - shutil.copyfile(cmap.mapFile, destfile) + # I think the colors attribute is only + # available on ListedColormap instances ... + data = cmap.mapObj.colors + np.savetxt(destFile, data, '%0.6f') cmap.installed = True @@ -688,21 +666,25 @@ def installColourMap(cmapName): def installLookupTable(lutName): """Attempts to install/save a previously registered lookup table into the ``fsl/fslview/luts`` directory. - - A ``KeyError`` is raised if the lookup table is not registered, or an - ``IOError`` if the lookup table cannot be saved. """ # keyerror if not registered lut = _luts[lutName] - if lut.mapFile is not None: destFile = lut.mapFile - else: op.join(_lutDir, '{}.lut'.format(lutName)) + if lut.mapFile is not None: + destFile = lut.mapFile + else: + destFile = op.join( + _lutDir, + '{}.lut'.format(lutName.lower().replace(' ', '_'))) + + log.debug('Installing lookup table {} to {}'.format(lutName, destFile)) - lut.mapObj.save(destFile) + lut.mapObj._save(destFile) - lut.mapFile = destFile - lut.installed = True + lut.mapFile = destFile + lut.installed = True + lut.mapObj.saved = True ############### diff --git a/fsl/fslview/controls/lookuptablepanel.py b/fsl/fslview/controls/lookuptablepanel.py index 2ee5456d1..72f20ecc3 100644 --- a/fsl/fslview/controls/lookuptablepanel.py +++ b/fsl/fslview/controls/lookuptablepanel.py @@ -5,6 +5,7 @@ # Author: Paul McCarthy <pauldmccarthy@gmail.com> # +import os import logging import wx @@ -88,18 +89,7 @@ class LookupTablePanel(fslpanel.FSLViewPanel): fslpanel.FSLViewPanel.__init__(self, parent, overlayList, displayCtx) - # If non-lut image is shown, just show a message - - # Overlay name - # Change lookup table - # Add label - # New lut - # Copy lut - # Save lut - # Load lut - - self.__controlRow = wx.Panel(self) - + self.__controlRow = wx.Panel(self) self.__disabledLabel = wx.StaticText(self, style=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) @@ -178,6 +168,8 @@ class LookupTablePanel(fslpanel.FSLViewPanel): def destroy(self): + fslpanel.FSLViewPanel.destroy(self) + self._overlayList.removeListener('overlays', self._name) self._displayCtx .removeListener('selectedOverlay', self._name) @@ -373,11 +365,34 @@ class LookupTablePanel(fslpanel.FSLViewPanel): def __onLoadLut(self, ev): - pass + nameDlg = NewLutDialog(self.GetTopLevelParent()) + + if nameDlg.ShowModal() != wx.ID_OK: + return + + fileDlg = wx.FileDialog(wx.GetApp().GetTopWindow(), + message=strings.titles[self, 'loadLut'], + defaultDir=os.getcwd(), + style=wx.FD_OPEN) + + if fileDlg.ShowModal() != wx.ID_OK: + return + + name = nameDlg.name + path = fileDlg.GetPath() + + lut = fslcmaps.registerLookupTable(path, + self._overlayList, + self._displayCtx, + name) + + if self.__selectedOpts is not None: + self.__selectedOpts.lut = lut + def __onSaveLut(self, ev): - pass + fslcmaps.installLookupTable(self.__selectedLut.name) def __onLabelAdd(self, ev): -- GitLab