def loadColourMapFile(fname, aslut=False): """Load the given file, assumed to be a colour map. :arg fname: FSLeyes or FSLView (VEST) colour map file :arg aslut: If ``True``, the returned array will contain a label for each colour, ranging from ``1`` to ``N``, where ``N`` is the number of colours in the file. :returns: A ``numpy`` array of shape ``(N, 3)`` containing the RGB values for ``N`` colours. Or, if ``aslut is True``, A ``numpy`` array of shape ``(N, 4)`` containing a label, and the RGB values for ``N`` colours. """ # The file could be a FSLView style VEST LUT if vest.looksLikeVestLutFile(fname): data = vest.loadVestLutFile(fname, normalise=False) # Or just a plain 2D text array else: data = np.loadtxt(fname) if aslut: lbls = np.arange(1, data.shape[0] + 1).reshape(-1, 1) data = np.hstack((lbls, data)) return data
def test_loadVestLutFile(): testdir = tempfile.mkdtemp() testfiles = [ op.join(testdir, 'testfile1.txt'), op.join(testdir, 'testfile2.txt'), op.join(testdir, 'testfile3.txt'), op.join(testdir, 'testfile4.txt'), op.join(testdir, 'testfile5.txt')] testdata = [ testfile1Colours, testfile2Colours, testfile3Colours, testfile4Colours] try: _createFiles(testdir) with pytest.raises(Exception): vest.loadVestLutFile(testfiles[4]) vest.loadVestLutFile(testfiles[4], normalise=False) for i in range(4): f = testfiles[i] d = testdata[ i] with warnings.catch_warnings(): warnings.simplefilter('ignore') dnorm = (d - d.min()) / (d.max() - d.min()) lutnorm = vest.loadVestLutFile(f) lut = vest.loadVestLutFile(f, normalise=False) assert lut.shape == d.shape assert lutnorm.shape == dnorm.shape assert np.all(np.isclose(lut, d)) if (d.max() - d.min()) != 0: assert np.all(np.isclose(lutnorm, dnorm)) else: assert np.all(np.isnan(dnorm)) assert np.all(np.isnan(lutnorm)) finally: shutil.rmtree(testdir)
def registerColourMap(cmapFile, overlayList=None, displayCtx=None, key=None, name=None): """Loads RGB data from the given file, and registers it as a :mod:`matplotlib` :class:`~matplotlib.colors.ListedColormap` instance. .. note:: If the ``overlayList`` and ``displayContext`` arguments are provided, the ``cmap`` property of all :class:`.VolumeOpts` instances are updated to support the new colour map. :arg cmapFile: Name of a file containing RGB values :arg overlayList: A :class:`.OverlayList` instance which contains all overlays that are being displayed (can be ``None``). :arg displayCtx: A :class:`.DisplayContext` instance describing how the overlays in ``overlayList`` are being displayed. Must be provided if ``overlayList`` is provided. :arg key: Name to give the colour map. If ``None``, defaults to the file name prefix. :arg name: Display name for the colour map. If ``None``, defaults to the ``name``. """ import matplotlib.cm as mplcm import matplotlib.colors as colors if key is not None and not isValidMapKey(key): raise ValueError('{} is not a valid colour map identifier'.format(key)) if key is None: key = op.basename(cmapFile).split('.')[0] key = makeValidMapKey(key) if name is None: name = key if overlayList is None: overlayList = [] # The file could be a FSLView style VEST-LUT if vest.looksLikeVestLutFile(cmapFile): data = vest.loadVestLutFile(cmapFile, normalise=False) # Or just a plain 2D text array else: data = np.loadtxt(cmapFile) cmap = colors.ListedColormap(data, key) log.debug('Loading and registering custom ' 'colour map: {}'.format(cmapFile)) mplcm.register_cmap(key, cmap) _cmaps[key] = _Map(key, name, cmap, cmapFile, False) log.debug('Patching DisplayOpts instances and class ' 'to support new colour map {}'.format(key)) import fsleyes.displaycontext as fsldisplay # A list of all DisplayOpts colour map properties. # n.b. We can't simply list the ColourMapOpts class # here, because it is a mixin, and does not actually # derive from props.HasProperties. # # TODO Any new DisplayOpts sub-types which have a # colour map will need to be patched here cmapProps = [] cmapProps.append((fsldisplay.VolumeOpts, 'cmap')) cmapProps.append((fsldisplay.VolumeOpts, 'negativeCmap')) cmapProps.append((fsldisplay.VectorOpts, 'cmap')) cmapProps.append((fsldisplay.MeshOpts, 'cmap')) cmapProps.append((fsldisplay.MeshOpts, 'negativeCmap')) # Update the colour map properties # for any existing instances for overlay in overlayList: opts = displayCtx.getOpts(overlay) for cls, propName in cmapProps: if isinstance(opts, cls): prop = opts.getProp(propName) prop.addColourMap(key, opts) # and for all future overlays for cls, propName in cmapProps: prop = cls.getProp(propName) prop.addColourMap(key)