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

VectorOpts.clipThreshold is now a range called VectorOpts.clippingRange.

parent 9dbd4ec1
No related branches found
No related tags found
No related merge requests found
......@@ -555,7 +555,7 @@ properties = TypeDict({
'VectorOpts.suppressZ' : 'Suppress Z value',
'VectorOpts.modulateImage' : 'Modulate by',
'VectorOpts.clipImage' : 'Clip by',
'VectorOpts.clipThreshold' : 'Clipping threshold',
'VectorOpts.clippingRange' : 'Clipping range',
'RGBVectorOpts.interpolation' : 'Interpolation',
......@@ -619,6 +619,9 @@ choices = TypeDict({
'VectorOpts.modulateImage.none' : 'No modulation',
'VectorOpts.clipImage.none' : 'No clipping',
'VectorOpts.clippingRange.min' : 'Min.',
'VectorOpts.clippingRange.max' : 'Max.',
'ModelOpts.refImage.none' : 'No reference image',
......
......@@ -326,7 +326,8 @@ _DISPLAY_PROPS = td.TypeDict({
'RGBVectorOpts' : [
props.Widget('resolution', showLimits=False),
props.Widget('interpolation'),
props.Widget('interpolation',
labels=strings.choices['VolumeOpts.interpolation']),
props.Widget('xColour'),
props.Widget('yColour'),
props.Widget('zColour'),
......@@ -335,9 +336,11 @@ _DISPLAY_PROPS = td.TypeDict({
props.Widget('suppressZ'),
props.Widget('modulateImage', labels=_imageName),
props.Widget('clipImage', labels=_imageName),
props.Widget('clipThreshold',
props.Widget('clippingRange',
showLimits=False,
spin=False,
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None)],
......@@ -353,9 +356,11 @@ _DISPLAY_PROPS = td.TypeDict({
props.Widget('lineWidth', showLimits=False),
props.Widget('modulateImage', labels=_imageName),
props.Widget('clipImage', labels=_imageName),
props.Widget('clipThreshold',
props.Widget('clippingRange',
showLimits=False,
spin=False,
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None)],
......@@ -386,10 +391,11 @@ _DISPLAY_PROPS = td.TypeDict({
props.Widget('suppressZ'),
props.Widget('modulateImage', labels=_imageName),
props.Widget('clipImage', labels=_imageName),
props.Widget('clipThreshold',
props.Widget('clippingRange',
showLimits=False,
spin=False,
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None)],
......
......@@ -331,7 +331,7 @@ class OverlayDisplayToolBar(fsltoolbar.FSLEyesToolBar):
"""
modSpec = _TOOLBAR_PROPS[opts]['modulateImage']
thresSpec = _TOOLBAR_PROPS[opts]['clipThreshold']
thresSpec = _TOOLBAR_PROPS[opts]['clippingRange']
panel = wx.Panel(self)
sizer = wx.FlexGridSizer(2, 2)
......@@ -342,8 +342,7 @@ class OverlayDisplayToolBar(fsltoolbar.FSLEyesToolBar):
modLabel = wx.StaticText(panel)
thresLabel = wx.StaticText(panel)
modLabel .SetLabel(strings.properties[opts, 'modulateImage'])
thresLabel.SetLabel(strings.properties[opts, 'clipThreshold'])
modLabel.SetLabel(strings.properties[opts, 'modulateImage'])
sizer.Add(modLabel)
sizer.Add(modWidget, flag=wx.EXPAND)
......@@ -434,13 +433,13 @@ _TOOLTIPS = td.TypeDict({
'RGBVectorOpts.modulateImage' : fsltooltips.properties['VectorOpts.'
'modulateImage'],
'RGBVectorOpts.clipThreshold' : fsltooltips.properties['VectorOpts.'
'clipThreshold'],
'RGBVectorOpts.clippingRange' : fsltooltips.properties['VectorOpts.'
'clippingRange'],
'LineVectorOpts.modulateImage' : fsltooltips.properties['VectorOpts.'
'modulateImage'],
'LineVectorOpts.clipThreshold' : fsltooltips.properties['VectorOpts.'
'clipThreshold'],
'LineVectorOpts.clippingRange' : fsltooltips.properties['VectorOpts.'
'clippingRange'],
'LineVectorOpts.lineWidth' : fsltooltips.properties['LineVectorOpts.'
'lineWidth'],
......@@ -451,8 +450,8 @@ _TOOLTIPS = td.TypeDict({
'TensorOpts.modulateImage' : fsltooltips.properties['VectorOpts.'
'modulateImage'],
'TensorOpts.clipThreshold' : fsltooltips.properties['VectorOpts.'
'clipThreshold'],
'TensorOpts.clippingRange' : fsltooltips.properties['VectorOpts.'
'clippingRange'],
})
"""This dictionary contains tooltips for :class:`.Display` and
:class:`.DisplayOpts` properties. It is referenced in the
......@@ -536,22 +535,28 @@ _TOOLBAR_PROPS = td.TypeDict({
'modulateImage',
labels=_modImageLabel,
tooltip=_TOOLTIPS['RGBVectorOpts.modulateImage']),
'clipThreshold' : props.Widget(
'clipThreshold',
'clippingRange' : props.Widget(
'clippingRange',
showLimits=False,
spin=False,
tooltip=_TOOLTIPS['RGBVectorOpts.clipThreshold'])},
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None)},
'LineVectorOpts' : {
'modulateImage' : props.Widget(
'modulateImage',
labels=_modImageLabel,
tooltip=_TOOLTIPS['LineVectorOpts.modulateImage']),
'clipThreshold' : props.Widget(
'clipThreshold',
'clippingRange' : props.Widget(
'clippingRange',
showLimits=False,
spin=False,
tooltip=_TOOLTIPS['LineVectorOpts.clipThreshold']),
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None),
'lineWidth' : props.Widget(
'lineWidth',
showLimits=False,
......@@ -582,11 +587,14 @@ _TOOLBAR_PROPS = td.TypeDict({
'modulateImage',
labels=_modImageLabel,
tooltip=_TOOLTIPS['TensorOpts.modulateImage']),
'clipThreshold' : props.Widget(
'clipThreshold',
'clippingRange' : props.Widget(
'clippingRange',
showLimits=False,
spin=False,
tooltip=_TOOLTIPS['TensorOpts.clipThreshold'])}
slider=True,
labels=[strings.choices['VectorOpts.clippingRange.min'],
strings.choices['VectorOpts.clippingRange.max']],
dependencies=['clipImage'],
enabledWhen=lambda o, ci: ci is not None)}
})
"""This dictionary defines specifications for all controls shown on an
:class:`OverlayDisplayToolBar`.
......
......@@ -76,7 +76,7 @@ class OverlayGroup(props.HasProperties):
'suppressZ',
'modulateImage',
'clipImage',
'clipThreshold'],
'clippingRange'],
'LineVectorOpts' : ['lineWidth',
'directed'],
'RGBVectorOpts' : ['interpolation'],
......
......@@ -60,15 +60,13 @@ class VectorOpts(volumeopts.Nifti1Opts):
"""Clip voxels from the vector image according to another image. Any image
which is in the :class:`.OverlayList`, and which has the same voxel
dimensions as the vector image can be selected for clipping. The
:attr:`clipThreshold` dictates the value below which vector voxels are
:attr:`clippingRange` dictates the value below which vector voxels are
clipped.
"""
clipThreshold = props.Real(default=0.0, minval=0, maxval=1)
"""Hide voxels for which the modulation value is below this threshold,
as a percentage of the :attr:`modulate` image data range.
"""
clippingRange = props.Bounds(ndims=1)
"""Hide voxels for which the clip image value is outside of this range. """
def __init__(self, *args, **kwargs):
......@@ -105,20 +103,24 @@ class VectorOpts(volumeopts.Nifti1Opts):
def __clipImageChanged(self, *a):
"""Called when the :attr:`clipImage` property changes. Updates
the range of the :attr:`clipThreshold` property.
the range of the :attr:`clippingRange` property.
"""
image = self.clipImage
if image is None:
self.clippingRange.xmin = 0
self.clippingRange.xmax = 1
self.clippingRange.x = [0, 1]
return
opts = self.displayCtx.getOpts(image)
minval = opts.dataMin
maxval = opts.dataMax
self.setConstraint('clipThreshold', 'minval', minval)
self.setConstraint('clipThreshold', 'maxval', maxval)
self.clippingRange.xmin = minval
self.clippingRange.xmax = maxval
self.clippingRange.x = [minval, maxval]
def __overlayListChanged(self, *a):
......
......@@ -207,7 +207,7 @@ OPTIONS = td.TypeDict({
'suppressZ',
'modulateImage',
'clipImage',
'clipThreshold'],
'clippingRange'],
'LineVectorOpts' : ['lineWidth',
'directed'],
'RGBVectorOpts' : ['interpolation'],
......@@ -347,7 +347,7 @@ ARGUMENTS = td.TypeDict({
'VectorOpts.suppressZ' : ('zs', 'suppressZ'),
'VectorOpts.modulateImage' : ('md', 'modulateImage'),
'VectorOpts.clipImage' : ('cl', 'clipImage'),
'VectorOpts.clipThreshold' : ('ct', 'clipThreshold'),
'VectorOpts.clippingRange' : ('cp', 'clipRange'),
'LineVectorOpts.lineWidth' : ('lvw', 'lineWidth'),
'LineVectorOpts.directed' : ('lvi', 'directed'),
......@@ -453,9 +453,8 @@ HELP = td.TypeDict({
'VectorOpts.suppressZ' : 'Suppress Z magnitude',
'VectorOpts.modulateImage' : 'Modulate vector brightness',
'VectorOpts.clipImage' : 'Clip vector voxels',
'VectorOpts.clipThreshold' : 'Hide voxels where clip image '
'value is below this threshold '
'(expressed as a percentage)',
'VectorOpts.clippingRange' : 'Hide voxels where clip image '
'value is outside of this range.',
'LineVectorOpts.lineWidth' : 'Line width',
'LineVectorOpts.directed' : 'Interpret vectors as directed',
......
......@@ -101,9 +101,9 @@ def compileShaders(self):
'directed', 'imageDims']
fragUniforms = ['imageTexture', 'modulateTexture', 'clipTexture',
'clipThreshold', 'xColourTexture', 'yColourTexture',
'zColourTexture', 'voxValXform', 'cmapXform',
'imageShape', 'useSpline']
'clipLow', 'clipHigh', 'xColourTexture',
'yColourTexture', 'zColourTexture', 'voxValXform',
'cmapXform', 'imageShape', 'useSpline']
self.shaderVars = shaders.getShaderVars(self.shaders,
vertAtts,
......@@ -125,14 +125,21 @@ def updateShaderState(self):
voxValXform = self.imageTexture.voxValXform
useSpline = False
imageShape = np.array(image.shape[:3], dtype=np.float32)
clipThreshold = opts.clipThreshold
clippingRange = opts.clippingRange.x
voxValXform = np.array(voxValXform, dtype=np.float32).ravel('C')
cmapXform = np.array(cmapXform, dtype=np.float32).ravel('C')
invClipValXform = self.clipTexture .invVoxValXform
clipThreshold = clipThreshold * invClipValXform[0, 0] + \
invClipValXform[3, 0]
if opts.clipImage is not None:
invClipValXform = self.clipTexture .invVoxValXform
clipLow = clippingRange[0] * invClipValXform[0, 0] + \
invClipValXform[3, 0]
clipHigh = clippingRange[1] * invClipValXform[0, 0] + \
invClipValXform[3, 0]
else:
clipLow = 0
clipHigh = 1
gl.glUseProgram(self.shaders)
......@@ -142,7 +149,8 @@ def updateShaderState(self):
gl.glUniformMatrix4fv(svars['voxValXform'], 1, False, voxValXform)
gl.glUniformMatrix4fv(svars['cmapXform'], 1, False, cmapXform)
gl.glUniform1f(svars['clipThreshold'], clipThreshold)
gl.glUniform1f(svars['clipLow'], clipLow)
gl.glUniform1f(svars['clipHigh'], clipHigh)
gl.glUniform1i(svars['imageTexture'], 0)
gl.glUniform1i(svars['modulateTexture'], 1)
......
......@@ -66,9 +66,9 @@ def compileShaders(self):
vertAtts = ['vertex', 'voxCoord', 'texCoord']
fragUniforms = ['imageTexture', 'modulateTexture', 'clipTexture',
'clipThreshold', 'xColourTexture', 'yColourTexture',
'zColourTexture', 'voxValXform', 'cmapXform',
'imageShape', 'useSpline']
'clipLow', 'clipHigh', 'xColourTexture',
'yColourTexture', 'zColourTexture', 'voxValXform',
'cmapXform', 'imageShape', 'useSpline']
for va in vertAtts:
shaderVars[va] = gl.glGetAttribLocation(self.shaders, va)
......@@ -97,14 +97,20 @@ def updateShaderState(self):
cmapXform = self.xColourTexture.getCoordinateTransform()
useSpline = opts.interpolation == 'spline'
imageShape = np.array(self.vectorImage.shape, dtype=np.float32)
clipThreshold = opts.clipThreshold
clippingRange = opts.clippingRange
# Transform the clip threshold into
# the texture value range, so the
# fragment shader can compare texture
# values directly to it.
clipThreshold = clipThreshold * invClipValXform[0, 0] + \
invClipValXform[3, 0]
if opts.clipImage is not None:
clipLow = clippingRange[0] * \
invClipValXform[0, 0] + invClipValXform[3, 0]
clipHigh = clippingRange[1] * \
invClipValXform[0, 0] + invClipValXform[3, 0]
else:
clipLow = 0
clipHigh = 1
gl.glUseProgram(self.shaders)
......@@ -114,7 +120,8 @@ def updateShaderState(self):
gl.glUniformMatrix4fv(svars['voxValXform'], 1, False, voxValXform)
gl.glUniformMatrix4fv(svars['cmapXform'], 1, False, cmapXform)
gl.glUniform1f(svars['clipThreshold'], clipThreshold)
gl.glUniform1f(svars['clipLow'], clipLow)
gl.glUniform1f(svars['clipHigh'], clipHigh)
gl.glUniform1i(svars['imageTexture'], 0)
gl.glUniform1i(svars['modulateTexture'], 1)
gl.glUniform1i(svars['clipTexture'], 2)
......
......@@ -114,9 +114,9 @@ def compileShaders(self):
'eigValNorm', 'zax']
fragUniforms = ['imageTexture', 'modulateTexture', 'clipTexture',
'clipThreshold', 'xColourTexture', 'yColourTexture',
'zColourTexture', 'voxValXform', 'cmapXform',
'imageShape', 'useSpline']
'clipLow', 'clipHigh', 'xColourTexture',
'yColourTexture', 'zColourTexture', 'voxValXform',
'cmapXform', 'imageShape', 'useSpline']
self.shaderVars = shaders.getShaderVars(self.shaders,
......@@ -180,7 +180,7 @@ def updateShaderState(self):
# Other miscellaneous uniforms
imageShape = np.array(self.image.shape[:3], dtype=np.float32)
resolution = opts.tensorResolution
clipThreshold = opts.clipThreshold
clippingRange = opts.clippingRange
tensorScale = opts.tensorScale
lighting = 1 if opts.lighting else 0
useSpline = 0
......@@ -189,16 +189,23 @@ def updateShaderState(self):
eigValNorm = 0.5 / abs(l1.data).max()
eigValNorm *= tensorScale / 100.0
invClipValXform = self.clipTexture .invVoxValXform
clipThreshold = clipThreshold * invClipValXform[0, 0] + \
invClipValXform[3, 0]
gl.glUniform3fv(svars['imageShape'], 1, imageShape)
gl.glUniform1f( svars['resolution'], resolution)
gl.glUniform1f( svars['eigValNorm'], eigValNorm)
gl.glUniform1f( svars['lighting'], lighting)
gl.glUniform1f( svars['clipThreshold'], clipThreshold)
gl.glUniform1f( svars['useSpline'], useSpline)
if opts.clipImage is not None:
invClipValXform = self.clipTexture .invVoxValXform
clipLow = clippingRange[0] * invClipValXform[0, 0] + \
invClipValXform[3, 0]
clipHigh = clippingRange[1] * invClipValXform[0, 0] + \
invClipValXform[3, 0]
else:
clipLow = 0
clipHigh = 1
gl.glUniform3fv(svars['imageShape'], 1, imageShape)
gl.glUniform1f( svars['resolution'], resolution)
gl.glUniform1f( svars['eigValNorm'], eigValNorm)
gl.glUniform1f( svars['lighting'], lighting)
gl.glUniform1f( svars['clipLow'], clipLow)
gl.glUniform1f( svars['clipHigh'], clipHigh)
gl.glUniform1f( svars['useSpline'], useSpline)
# Vertices of a unit sphere. The vertex
# shader will transform these vertices
......
......@@ -29,10 +29,13 @@ uniform sampler3D clipTexture;
/*
* If the clipping value is below this
* threshold, the fragment is clipped.
* If the clipping value is outside of
* this range, the fragment is clipped.
* These values should be in the texture
* data range of the clipTexture.
*/
uniform float clipThreshold;
uniform float clipLow;
uniform float clipHigh;
/*
* Colour map for the X vector component.
......@@ -125,8 +128,8 @@ void main(void) {
clipValue = texture3D(clipTexture, fragTexCoord).x;
}
/* Knock out voxels where the clipping value is below the threshold */
if (clipValue < clipThreshold) {
/* Knock out voxels where the clipping value is outside the clipping range */
if (clipValue < clipLow || clipValue > clipHigh) {
gl_FragColor.a = 0.0;
return;
}
......
......@@ -212,7 +212,7 @@ class GLVector(globject.GLImageObject):
opts .addListener('suppressZ', name, cmapUpdate, weak=False)
opts .addListener('modulateImage', name, modUpdate, weak=False)
opts .addListener('clipImage', name, clipUpdate, weak=False)
opts .addListener('clipThreshold', name, shaderUpdate, weak=False)
opts .addListener('clippingRange', name, shaderUpdate, weak=False)
opts .addListener('resolution', name, imageUpdate, weak=False)
opts .addListener('transform', name, update, weak=False)
......@@ -244,7 +244,7 @@ class GLVector(globject.GLImageObject):
opts .removeListener('suppressZ', name)
opts .removeListener('modulateImage', name)
opts .removeListener('clipImage', name)
opts .removeListener('clipThreshold', name)
opts .removeListener('clippingRange', name)
opts .removeListener('volume', name)
opts .removeListener('resolution', name)
opts .removeListener('transform' , name)
......
......@@ -151,9 +151,9 @@ properties = TypeDict({
'not shown. The clipping image must have '
'the same voxel dimensions as the vector '
'image. ',
'VectorOpts.clipThreshold' : 'Vector values which have a corresponding '
'clipping image value that is less than '
'this threshold are not displayed. ',
'VectorOpts.clippingRange' : 'Vector values which have a corresponding '
'clipping image value that is outside of '
'this range are not displayed. ',
'LineVectorOpts.lineWidth' : 'The width of each vector line, in '
'display pixels.',
'LineVectorOpts.directed' : 'If unchecked, the vector data is assumed '
......
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