From b48ecb3dc9677eb4fd71a6e66db3004a8b41de18 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Mon, 1 Jun 2015 17:30:11 +0100 Subject: [PATCH] Initial implementation of Label images. Very rough right now. --- fsl/data/strings.py | 1 + fsl/fslview/displaycontext/__init__.py | 1 + fsl/fslview/displaycontext/display.py | 6 +- fsl/fslview/displaycontext/labelopts.py | 32 +++++ fsl/fslview/displaycontext/modelopts.py | 3 + fsl/fslview/gl/__init__.py | 1 + fsl/fslview/gl/gl21/__init__.py | 1 + fsl/fslview/gl/gl21/gllabel_frag.glsl | 83 +++++++++++ fsl/fslview/gl/gl21/gllabel_funcs.py | 71 ++++++++++ fsl/fslview/gl/gllabel.py | 133 ++++++++++++++++++ fsl/fslview/gl/globject.py | 4 +- fsl/fslview/gl/shaders.py | 7 +- fsl/fslview/gl/textures/__init__.py | 1 + fsl/fslview/gl/textures/lookuptabletexture.py | 103 ++++++++++++++ fsl/fslview/layouts.py | 8 +- fsl/fslview/lookuptables.py | 86 +++++++++++ fsl/fslview/luts/harvard-oxford-cortical.txt | 48 +++++++ 17 files changed, 584 insertions(+), 5 deletions(-) create mode 100644 fsl/fslview/displaycontext/labelopts.py create mode 100644 fsl/fslview/gl/gl21/gllabel_frag.glsl create mode 100644 fsl/fslview/gl/gl21/gllabel_funcs.py create mode 100644 fsl/fslview/gl/gllabel.py create mode 100644 fsl/fslview/gl/textures/lookuptabletexture.py create mode 100644 fsl/fslview/lookuptables.py create mode 100644 fsl/fslview/luts/harvard-oxford-cortical.txt diff --git a/fsl/data/strings.py b/fsl/data/strings.py index 047a8c0b4..aa6b48b08 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -316,6 +316,7 @@ choices = TypeDict({ 'Display.overlayType.volume' : '3D/4D volume', 'Display.overlayType.mask' : '3D/4D mask image', + 'Display.overlayType.label' : 'Label image', 'Display.overlayType.rgbvector' : '3-direction vector image (RGB)', 'Display.overlayType.linevector' : '3-direction vector image (Line)', 'Display.overlayType.model' : '3D model' diff --git a/fsl/fslview/displaycontext/__init__.py b/fsl/fslview/displaycontext/__init__.py index 0cad30f68..a70f549b0 100644 --- a/fsl/fslview/displaycontext/__init__.py +++ b/fsl/fslview/displaycontext/__init__.py @@ -20,6 +20,7 @@ from maskopts import MaskOpts from vectoropts import VectorOpts from vectoropts import LineVectorOpts from modelopts import ModelOpts +from labelopts import LabelOpts ALL_OVERLAY_TYPES = list(set( diff --git a/fsl/fslview/displaycontext/display.py b/fsl/fslview/displaycontext/display.py index 534ac88e2..5fd7329a4 100644 --- a/fsl/fslview/displaycontext/display.py +++ b/fsl/fslview/displaycontext/display.py @@ -244,12 +244,13 @@ class Display(props.SyncableHasProperties): import volumeopts import vectoropts import maskopts +import labelopts import modelopts OVERLAY_TYPES = td.TypeDict({ - 'Image' : ['volume', 'mask', 'rgbvector', 'linevector'], + 'Image' : ['volume', 'mask', 'rgbvector', 'linevector', 'label'], 'Model' : ['model'] }) """This dictionary provides a mapping between the overlay classes, and @@ -265,7 +266,8 @@ DISPLAY_OPTS_MAP = { 'rgbvector' : vectoropts.VectorOpts, 'linevector' : vectoropts.LineVectorOpts, 'mask' : maskopts. MaskOpts, - 'model' : modelopts. ModelOpts + 'model' : modelopts. ModelOpts, + 'label' : labelopts. LabelOpts, } """This dictionary provides a mapping between each overlay type, and the :class:`DisplayOpts` subclass which contains overlay type-specific diff --git a/fsl/fslview/displaycontext/labelopts.py b/fsl/fslview/displaycontext/labelopts.py new file mode 100644 index 000000000..f644d1587 --- /dev/null +++ b/fsl/fslview/displaycontext/labelopts.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# +# labelopts.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import props + +import volumeopts + +import fsl.fslview.lookuptables as lookuptables + + +class LabelOpts(volumeopts.ImageOpts): + + + lut = props.Choice() + outline = props.Boolean(default=False) + showNames = props.Boolean(default=False) + + + def __init__(self, overlay, *args, **kwargs): + + luts = lookuptables.all_luts + names = [lut.lutName() for lut in luts] + + self.getProp('lut').setChoices(luts, names, self) + + self.lut = luts[0] + + volumeopts.ImageOpts.__init__(self, overlay, *args, **kwargs) diff --git a/fsl/fslview/displaycontext/modelopts.py b/fsl/fslview/displaycontext/modelopts.py index 530d4c94e..254bf1b2a 100644 --- a/fsl/fslview/displaycontext/modelopts.py +++ b/fsl/fslview/displaycontext/modelopts.py @@ -28,6 +28,9 @@ class ModelOpts(fsldisplay.DisplayOpts): outline = props.Boolean(default=False) + + showName = props.Boolean(default=False) + refImage = props.Choice() diff --git a/fsl/fslview/gl/__init__.py b/fsl/fslview/gl/__init__.py index d0f7e3b21..a35cbbbe1 100644 --- a/fsl/fslview/gl/__init__.py +++ b/fsl/fslview/gl/__init__.py @@ -212,6 +212,7 @@ def bootstrap(glVersion=None): thismod.glrgbvector_funcs = glpkg.glrgbvector_funcs thismod.gllinevector_funcs = glpkg.gllinevector_funcs thismod.glmodel_funcs = glpkg.glmodel_funcs + thismod.gllabel_funcs = glpkg.gllabel_funcs thismod._bootstrapped = True diff --git a/fsl/fslview/gl/gl21/__init__.py b/fsl/fslview/gl/gl21/__init__.py index 5e1427459..2c0843a8b 100644 --- a/fsl/fslview/gl/gl21/__init__.py +++ b/fsl/fslview/gl/gl21/__init__.py @@ -9,3 +9,4 @@ import glvolume_funcs import glrgbvector_funcs import gllinevector_funcs import glmodel_funcs +import gllabel_funcs diff --git a/fsl/fslview/gl/gl21/gllabel_frag.glsl b/fsl/fslview/gl/gl21/gllabel_frag.glsl new file mode 100644 index 000000000..d5eb3a682 --- /dev/null +++ b/fsl/fslview/gl/gl21/gllabel_frag.glsl @@ -0,0 +1,83 @@ +#version 120 + +#pragma include spline_interp.glsl +#pragma include test_in_bounds.glsl + +uniform sampler3D imageTexture; + +uniform sampler1D lutTexture; + +uniform mat4 voxValXform; + +uniform vec3 imageShape; + +uniform float numLabels; + +uniform bool useSpline; + +uniform bool outline; + +varying vec3 fragVoxCoord; + +varying vec3 fragTexCoord; + + +void main(void) { + + vec3 voxCoord = fragVoxCoord; + + if (!test_in_bounds(voxCoord, imageShape)) { + + gl_FragColor = vec4(0, 0, 0, 0); + return; + } + + float voxValue; + if (useSpline) voxValue = spline_interp(imageTexture, + fragTexCoord, + imageShape, + 0); + else voxValue = texture3D( imageTexture, + fragTexCoord).r; + + float lutCoord = (voxValXform * vec4(voxValue, 0, 0, 1)).x / numLabels; + vec4 colour = texture1D(lutTexture, lutCoord); + + if (outline) { + + // TODO take into account resolution + vec3 off = 0.1 / imageShape; + + float left = texture3D(imageTexture, + fragTexCoord + vec3(-off.x, 0, 0)) .r; + float right = texture3D(imageTexture, + fragTexCoord + vec3( off.x, 0, 0)) .r; + float top = texture3D(imageTexture, + fragTexCoord + vec3( 0, off.y, 0)) .r; + float bottom = texture3D(imageTexture, + fragTexCoord + vec3( 0, -off.y, 0)) .r; + float back = texture3D(imageTexture, + fragTexCoord + vec3( 0, 0, -off.z)).r; + float front = texture3D(imageTexture, + fragTexCoord + vec3( 0, 0, off.z)).r; + + + voxValue = (voxValXform * vec4(voxValue, 0, 0, 1)).x; + left = (voxValXform * vec4(left, 0, 0, 1)).x; + right = (voxValXform * vec4(right, 0, 0, 1)).x; + top = (voxValXform * vec4(top, 0, 0, 1)).x; + bottom = (voxValXform * vec4(bottom, 0, 0, 1)).x; + back = (voxValXform * vec4(back, 0, 0, 1)).x; + front = (voxValXform * vec4(front, 0, 0, 1)).x; + + if (abs(voxValue - top) < 0.001 && + abs(voxValue - bottom) < 0.001 && + abs(voxValue - left) < 0.001 && + abs(voxValue - right) < 0.001 && + abs(voxValue - back) < 0.001 && + abs(voxValue - front) < 0.001) + colour.a = 0.0; + } + + gl_FragColor = colour; +} diff --git a/fsl/fslview/gl/gl21/gllabel_funcs.py b/fsl/fslview/gl/gl21/gllabel_funcs.py new file mode 100644 index 000000000..8a7e4dbf9 --- /dev/null +++ b/fsl/fslview/gl/gl21/gllabel_funcs.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# gllabel_funcs.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import OpenGL.GL as gl +import numpy as np + +import fsl.fslview.gl.shaders as shaders +import glvolume_funcs + + +def compileShaders(self): + + vertShaderSrc = shaders.getVertexShader( self, + sw=self.display.softwareMode) + fragShaderSrc = shaders.getFragmentShader(self, + sw=self.display.softwareMode) + self.shaders = shaders.compileShaders(vertShaderSrc, fragShaderSrc) + + self.vertexPos = gl.glGetAttribLocation( self.shaders, + 'vertex') + self.voxCoordPos = gl.glGetAttribLocation( self.shaders, + 'voxCoord') + self.texCoordPos = gl.glGetAttribLocation( self.shaders, + 'texCoord') + self.imageTexturePos = gl.glGetUniformLocation(self.shaders, + 'imageTexture') + self.lutTexturePos = gl.glGetUniformLocation(self.shaders, + 'lutTexture') + self.voxValXformPos = gl.glGetUniformLocation(self.shaders, + 'voxValXform') + self.imageShapePos = gl.glGetUniformLocation(self.shaders, + 'imageShape') + self.useSplinePos = gl.glGetUniformLocation(self.shaders, + 'useSpline') + self.numLabelsPos = gl.glGetUniformLocation(self.shaders, + 'numLabels') + self.outlinePos = gl.glGetUniformLocation(self.shaders, + 'outline') + + +def updateShaderState(self): + + display = self.display + opts = self.displayOpts + + gl.glUseProgram(self.shaders) + + + gl.glUniform1f( self.outlinePos, opts.outline) + gl.glUniform1f( self.numLabelsPos, 64) + gl.glUniform1f( self.useSplinePos, display.interpolation == 'spline') + gl.glUniform3fv(self.imageShapePos, 1, np.array(self.image.shape[:3], + dtype=np.float32)) + + vvx = self.imageTexture.voxValXform.ravel('C') + gl.glUniformMatrix4fv(self.voxValXformPos, 1, False, vvx) + + gl.glUniform1i(self.imageTexturePos, 0) + gl.glUniform1i(self.lutTexturePos, 1) + + gl.glUseProgram(0) + + +preDraw = glvolume_funcs.preDraw +draw = glvolume_funcs.draw +drawAll = glvolume_funcs.drawAll +postDraw = glvolume_funcs.postDraw diff --git a/fsl/fslview/gl/gllabel.py b/fsl/fslview/gl/gllabel.py new file mode 100644 index 000000000..f50fa5bed --- /dev/null +++ b/fsl/fslview/gl/gllabel.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# gllabel.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import OpenGL.GL as gl + +import fsl.utils.transform as transform +import fsl.fslview.gl as fslgl +import resources as glresources +import routines as glroutines +import globject +import textures + + +class GLLabel(globject.GLImageObject): + + + def __init__(self, image, display): + + globject.GLImageObject.__init__(self, image, display) + + + imageTexName = '{}_{}' .format(type(self).__name__, id(image)) + lutTexName = '{}_lut'.format(self.name) + + self.lutTexture = textures.LookupTableTexture(lutTexName) + self.imageTexture = glresources.get( + imageTexName, + textures.ImageTexture, + imageTexName, + image, + display) + + self.vertexAttrBuffer = gl.glGenBuffers(1) + + fslgl.gllabel_funcs.compileShaders( self) + fslgl.gllabel_funcs.updateShaderState(self) + + self.refreshLutTexture() + + self.addListeners() + + + def addListeners(self): + + display = self.display + opts = self.displayOpts + + def shaderUpdate(*a): + fslgl.gllabel_funcs.updateShaderState(self) + self.onUpdate() + + def lutUpdate(*a): + self.refreshLutTexture() + self.onUpdate() + + opts .addListener('outline', self.name, shaderUpdate) + opts .addListener('lut', self.name, lutUpdate) + display.addListener('alpha', self.name, lutUpdate) + display.addListener('brightness', self.name, lutUpdate) + display.addListener('contrast', self.name, lutUpdate) + + + def removeListeners(self): + display = self.display + opts = self.displayOpts + + opts .removeListener('outline', self.name) + opts .removeListener('lut', self.name) + display.removeListener('alpha', self.name) + display.removeListener('brightness', self.name) + display.removeListener('contrast', self.name) + + + def destroy(self): + + glresources.delete(self.imageTexture.getTextureName()) + self.lutTexture.destroy() + + self.removeListeners() + fslgl.gllabel_funcs.destroy(self) + + + def setAxes(self, xax, yax): + """This method should be called when the image display axes change.""" + + self.xax = xax + self.yax = yax + self.zax = 3 - xax - yax + + + def generateVertices(self, zpos, xform): + vertices, voxCoords, texCoords = glroutines.slice2D( + self.image.shape[:3], + self.xax, + self.yax, + zpos, + self.displayOpts.getTransform('voxel', 'display'), + self.displayOpts.getTransform('display', 'voxel')) + + if xform is not None: + vertices = transform.transform(vertices, xform) + + return vertices, voxCoords, texCoords + + + def refreshLutTexture(self, *a): + + display = self.display + opts = self.displayOpts + + self.lutTexture.set(alpha=display.alpha / 100.0, + lut=opts.lut) + + + def preDraw(self): + + self.imageTexture.bindTexture(gl.GL_TEXTURE0) + self.lutTexture .bindTexture(gl.GL_TEXTURE1) + fslgl.gllabel_funcs.preDraw(self) + + + def draw(self, zpos, xform=None): + fslgl.gllabel_funcs.draw(self, zpos, xform) + + + def postDraw(self): + self.imageTexture.unbindTexture() + self.lutTexture .unbindTexture() + fslgl.gllabel_funcs.postDraw(self) diff --git a/fsl/fslview/gl/globject.py b/fsl/fslview/gl/globject.py index 8466cd6c0..41dea3119 100644 --- a/fsl/fslview/gl/globject.py +++ b/fsl/fslview/gl/globject.py @@ -240,6 +240,7 @@ import glmask import glrgbvector import gllinevector import glmodel +import gllabel GLOBJECT_OVERLAY_TYPE_MAP = { @@ -247,7 +248,8 @@ GLOBJECT_OVERLAY_TYPE_MAP = { 'mask' : glmask .GLMask, 'rgbvector' : glrgbvector .GLRGBVector, 'linevector' : gllinevector.GLLineVector, - 'model' : glmodel .GLModel + 'model' : glmodel .GLModel, + 'label' : gllabel .GLLabel } """This dictionary provides a mapping between all available overlay types (see the :attr:`.Display.overlayType` property), and the :class:`GLObject` subclass diff --git a/fsl/fslview/gl/shaders.py b/fsl/fslview/gl/shaders.py index fc4d01e14..7b966a37c 100644 --- a/fsl/fslview/gl/shaders.py +++ b/fsl/fslview/gl/shaders.py @@ -37,6 +37,11 @@ _shaderTypePrefixMap = td.TypeDict({ ('GLVolume', 'vert', True) : 'glvolume_sw', ('GLVolume', 'frag', False) : 'glvolume', ('GLVolume', 'frag', True) : 'glvolume_sw', + + ('GLLabel', 'vert', False) : 'glvolume', + ('GLLabel', 'vert', True) : 'glvolume_sw', + ('GLLabel', 'frag', False) : 'gllabel', + ('GLLabel', 'frag', True) : 'gllabel_sw', ('GLRGBVector', 'vert', False) : 'glvolume', ('GLRGBVector', 'vert', True) : 'glvolume_sw', @@ -53,7 +58,7 @@ _shaderTypePrefixMap = td.TypeDict({ ('GLModel', 'vert', False) : 'glmodel', ('GLModel', 'vert', True) : 'glmodel', ('GLModel', 'frag', False) : 'glmodel', - ('GLModel', 'frag', True) : 'glmodel', + ('GLModel', 'frag', True) : 'glmodel', }) """This dictionary provides a mapping between :class:`.GLObject` types, and file name prefixes, identifying the shader programs to use. diff --git a/fsl/fslview/gl/textures/__init__.py b/fsl/fslview/gl/textures/__init__.py index a10bec9ac..8ddaf9bc7 100644 --- a/fsl/fslview/gl/textures/__init__.py +++ b/fsl/fslview/gl/textures/__init__.py @@ -19,6 +19,7 @@ from texture import Texture from texture import Texture2D from imagetexture import ImageTexture from colourmaptexture import ColourMapTexture +from lookuptabletexture import LookupTableTexture from selectiontexture import SelectionTexture from rendertexture import RenderTexture from rendertexture import GLObjectRenderTexture diff --git a/fsl/fslview/gl/textures/lookuptabletexture.py b/fsl/fslview/gl/textures/lookuptabletexture.py new file mode 100644 index 000000000..8cb2ec93f --- /dev/null +++ b/fsl/fslview/gl/textures/lookuptabletexture.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# lookuptabletexture.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import logging + +import OpenGL.GL as gl +import numpy as np + +import texture + + +log = logging.getLogger(__name__) + + +class LookupTableTexture(texture.Texture): + + def __init__(self, name): + + texture.Texture.__init__(self, name, 1) + + self.__lut = None + self.__alpha = None + self.__border = None + + + def set(self, **kwargs): + + lut = kwargs.get('lut', self) + alpha = kwargs.get('alpha', self) + border = kwargs.get('border', self) + + if lut is not self: self.__lut = lut + if alpha is not self: self.__alpha = alpha + if border is not self: self.__border = border + + self.__refresh() + + + def refresh(self): + self.__refresh() + + + def __refresh(self): + + alpha = self.__alpha + border = self.__border + + # TODO check maximum lut label value, + # and use corresponding number + # of slots in colour map + data = np.zeros((64, 4), dtype=np.uint8) + + if self.__lut is not None: + values = self.__lut.values() + colours = self.__lut.colours() + + for value, colour in zip(values, colours): + + data[value, :3] = [np.floor(c * 255) for c in colour] + + if alpha is not None: data[value, 3] = alpha * 255 + else: data[value, 3] = 255 + + + data = data.ravel('C') + + self.bindTexture() + + if border is not None: + if alpha is not None: + border[3] = alpha * 255 + + gl.glTexParameterfv(gl.GL_TEXTURE_1D, + gl.GL_TEXTURE_BORDER_COLOR, + border) + gl.glTexParameteri( gl.GL_TEXTURE_1D, + gl.GL_TEXTURE_WRAP_S, + gl.GL_CLAMP_TO_BORDER) + else: + gl.glTexParameteri(gl.GL_TEXTURE_1D, + gl.GL_TEXTURE_WRAP_S, + gl.GL_CLAMP_TO_EDGE) + + gl.glTexParameteri(gl.GL_TEXTURE_1D, + gl.GL_TEXTURE_MAG_FILTER, + gl.GL_NEAREST) + gl.glTexParameteri(gl.GL_TEXTURE_1D, + gl.GL_TEXTURE_MIN_FILTER, + gl.GL_NEAREST) + + gl.glTexImage1D(gl.GL_TEXTURE_1D, + 0, + gl.GL_RGBA8, + 64, + 0, + gl.GL_RGBA, + gl.GL_UNSIGNED_BYTE, + data) + self.unbindTexture() diff --git a/fsl/fslview/layouts.py b/fsl/fslview/layouts.py index 325bbf729..6e2242bba 100644 --- a/fsl/fslview/layouts.py +++ b/fsl/fslview/layouts.py @@ -32,6 +32,7 @@ from fsl.fslview.displaycontext import MaskOpts from fsl.fslview.displaycontext import VectorOpts from fsl.fslview.displaycontext import LineVectorOpts from fsl.fslview.displaycontext import ModelOpts +from fsl.fslview.displaycontext import LabelOpts from fsl.fslview.displaycontext import SceneOpts from fsl.fslview.displaycontext import OrthoOpts @@ -171,7 +172,11 @@ ModelOptsToolBarLayout = [ widget(ModelOpts, 'colour'), widget(ModelOpts, 'outline'), widget(ModelOpts, 'refImage'), - actions.ActionButton(OverlayDisplayToolBar, 'more')] + actions.ActionButton(OverlayDisplayToolBar, 'more')] + +LabelOptsToolBarLayout = [ + widget(LabelOpts, 'lut'), + widget(LabelOpts, 'outline')] DisplayLayout = props.VGroup( @@ -277,6 +282,7 @@ layouts = td.TypeDict({ ('OverlayDisplayToolBar', 'MaskOpts') : MaskOptsToolBarLayout, ('OverlayDisplayToolBar', 'VectorOpts') : VectorOptsToolBarLayout, ('OverlayDisplayToolBar', 'ModelOpts') : ModelOptsToolBarLayout, + ('OverlayDisplayToolBar', 'LabelOpts') : LabelOptsToolBarLayout, ('OverlayDisplayPanel', 'Display') : DisplayLayout, ('OverlayDisplayPanel', 'VolumeOpts') : VolumeOptsLayout, diff --git a/fsl/fslview/lookuptables.py b/fsl/fslview/lookuptables.py new file mode 100644 index 000000000..e433efff6 --- /dev/null +++ b/fsl/fslview/lookuptables.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# lookuptables.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + + +class LookupTable(object): + + + def __init__(self, lutName): + self.__lutName = lutName + self.__names = {} + self.__colours = {} + + + def __len__(self): + return len(self.__names.keys()) + + + def lutName(self): + return self.__lutName + + + def values(self): + return sorted(self.__names.keys()) + + + def names(self): + return [self.__names[v] for v in self.values()] + + + def colours(self): + return [self.__colours[v] for v in self.values()] + + + def name(self, value): + return self.__names[value] + + + def colour(self, value): + return self.__colours[value] + + + def set(self, value, name, colour): + + # At the moment, we are restricting + # lookup tables to be unsigned 16 bit. + # See gl/textures/lookuptabletexture.py + if not isinstance(value, (int, long)) or \ + value < 0 or value > 65535: + raise ValueError('Lookup table values must be ' + '16 bit unsigned integers.') + + self.__names[ value] = name + self.__colours[value] = colour + + + def load(self, lutFile): + + with open(lutFile, 'rt') as f: + lines = f.readlines() + + for line in lines: + tkns = line.split() + + label = int( tkns[0]) + r = float( tkns[1]) + g = float( tkns[2]) + b = float( tkns[3]) + lName = ' '.join(tkns[4:]) + + self.set(label, lName, (r, g, b)) + + return self + + +import os.path as op + +all_luts = [] +dirname = op.join(op.dirname(__file__), 'luts') + +all_luts.append( + LookupTable('Harvard-Oxford').load( + op.join(dirname, 'harvard-oxford-cortical.txt'))) diff --git a/fsl/fslview/luts/harvard-oxford-cortical.txt b/fsl/fslview/luts/harvard-oxford-cortical.txt new file mode 100644 index 000000000..8863dc889 --- /dev/null +++ b/fsl/fslview/luts/harvard-oxford-cortical.txt @@ -0,0 +1,48 @@ +1 0.00000 0.93333 0.00000 Frontal Pole +2 0.62745 0.32157 0.17647 Insular Cortex +3 1.00000 0.85490 0.72549 Superior Frontal Gyrus +4 0.00000 0.80784 0.81961 Middle Frontal Gyrus +5 0.49804 1.00000 0.83137 Inferior Frontal Gyrus, pars triangularis +6 0.69804 0.13333 0.13333 Inferior Frontal Gyrus, pars opercularis +7 0.93333 0.00000 0.00000 Precentral Gyrus +8 0.13333 0.54510 0.13333 Temporal Pole +9 0.81569 0.12549 0.56471 Superior Temporal Gyrus, anterior division +10 0.67843 1.00000 0.18431 Superior Temporal Gyrus, posterior division +11 0.94118 0.90196 0.54902 Middle Temporal Gyrus, anterior division +12 0.67843 0.84706 0.90196 Middle Temporal Gyrus, posterior division +13 0.93333 0.93333 0.00000 Middle Temporal Gyrus, temporooccipital part +14 0.19608 0.80392 0.19608 Inferior Temporal Gyrus, anterior division +15 1.00000 0.00000 1.00000 Inferior Temporal Gyrus, posterior division +16 0.69020 0.18824 0.37647 Inferior Temporal Gyrus, temporooccipital part +17 0.00000 1.00000 0.49804 Postcentral Gyrus +18 0.96078 0.87059 0.70196 Superior Parietal Lobule +19 1.00000 0.64706 0.00000 Supramarginal Gyrus, anterior division +20 1.00000 0.27059 0.00000 Supramarginal Gyrus, posterior division +21 0.80392 0.35686 0.27059 Angular Gyrus +22 1.00000 0.75294 0.79608 Lateral Occipital Cortex, superior division +23 0.59608 0.98431 0.59608 Lateral Occipital Cortex, inferior division +24 0.39216 0.58431 0.92941 Intracalcarine Cortex +25 0.62745 0.12549 0.94118 Frontal Medial Cortex +26 0.93333 0.50980 0.93333 Juxtapositional Lobule Cortex (formerly Supplementary Motor Cortex) +27 0.93333 0.78824 0.00000 Subcallosal Cortex +28 0.85490 0.43922 0.83922 Paracingulate Gyrus +29 1.00000 0.24314 0.58824 Cingulate Gyrus, anterior division +30 0.00000 0.00000 1.00000 Cingulate Gyrus, posterior division +31 0.15294 0.25098 0.54510 Precuneous Cortex +32 0.98039 0.50196 0.44706 Cuneal Cortex +33 1.00000 0.43137 0.70588 Frontal Orbital Cortex +34 1.00000 0.38824 0.27843 Parahippocampal Gyrus, anterior division +35 1.00000 1.00000 0.00000 Parahippocampal Gyrus, posterior division +36 0.00000 0.39216 0.00000 Lingual Gyrus +37 0.80392 0.36078 0.36078 Temporal Fusiform Cortex, anterior division +38 0.64706 0.16471 0.16471 Temporal Fusiform Cortex, posterior division +39 0.60000 0.19608 0.80000 Temporal Occipital Fusiform Cortex +40 0.00000 1.00000 1.00000 Occipital Fusiform Gyrus +41 0.86667 0.62745 0.86667 Frontal Operculum Cortex +42 0.52941 0.80784 0.92157 Central Opercular Cortex +43 0.82353 0.70588 0.54902 Parietal Operculum Cortex +44 1.00000 0.84314 0.00000 Planum Polare +45 0.00000 0.00000 0.50196 Heschl's Gyrus (includes H1 and H2) +46 0.18039 0.54510 0.34118 Planum Temporale +47 0.40000 0.80392 0.66667 Supracalcarine Cortex +48 0.00000 1.00000 0.00000 Occipital Pole -- GitLab