From 9788dc49ef277833e33bdb0aeb477e7b049b502a Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Mon, 13 Jul 2015 15:12:16 +0100 Subject: [PATCH] New option on GLVolume instances to invert the clipping range. Used by ClusterPanel when display z stats. Not implemented in GL14 yet. New random lut that should have been in previous commit. --- fsl/data/strings.py | 11 +-- fsl/fslview/controls/clusterpanel.py | 12 ++- fsl/fslview/displaycontext/volumeopts.py | 10 ++- fsl/fslview/gl/gl21/glvolume_frag.glsl | 9 +- fsl/fslview/gl/gl21/glvolume_funcs.py | 9 +- fsl/fslview/gl/glvolume.py | 50 ++++++------ fsl/fslview/layouts.py | 1 + fsl/fslview/luts/random.lut | 100 +++++++++++++++++++++++ 8 files changed, 165 insertions(+), 37 deletions(-) create mode 100644 fsl/fslview/luts/random.lut diff --git a/fsl/data/strings.py b/fsl/data/strings.py index 321b1d6e5..15faf8bee 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -349,11 +349,12 @@ properties = TypeDict({ 'ImageOpts.transform' : 'Image transform', 'ImageOpts.volume' : 'Volume', - 'VolumeOpts.displayRange' : 'Display range', - 'VolumeOpts.clippingRange' : 'Clipping range', - 'VolumeOpts.cmap' : 'Colour map', - 'VolumeOpts.invert' : 'Invert colour map', - 'VolumeOpts.interpolation' : 'Interpolation', + 'VolumeOpts.displayRange' : 'Display range', + 'VolumeOpts.clippingRange' : 'Clipping range', + 'VolumeOpts.cmap' : 'Colour map', + 'VolumeOpts.invert' : 'Invert colour map', + 'VolumeOpts.invertClipping' : 'Invert clipping range', + 'VolumeOpts.interpolation' : 'Interpolation', 'MaskOpts.colour' : 'Colour', 'MaskOpts.invert' : 'Invert', diff --git a/fsl/fslview/controls/clusterpanel.py b/fsl/fslview/controls/clusterpanel.py index 3b99b1988..20ba3e1a2 100644 --- a/fsl/fslview/controls/clusterpanel.py +++ b/fsl/fslview/controls/clusterpanel.py @@ -106,12 +106,18 @@ class ClusterPanel(fslpanel.FSLViewPanel): log.debug('Adding Z-statistic {} to overlay list'.format(zstats.name)) self._overlayList.append(zstats) - opts = self._overlayList.getOpts(zstats) - zthres = overlay.thresholds()['z'] + opts = self._displayCtx.getOpts(zstats) + zthres = float(overlay.thresholds()['z']) if zthres is not None: + + absmax = max(map(abs, (opts.dataMin, opts.dataMax))) + # Set clipping range - pass + opts.cmap = 'Render3' + opts.invertClipping = True + opts.displayRange.x = -absmax, absmax + opts.clippingRange.x = -zthres, zthres def __addClusterMaskClick(self, ev): diff --git a/fsl/fslview/displaycontext/volumeopts.py b/fsl/fslview/displaycontext/volumeopts.py index 42c6a6966..e20d3c525 100644 --- a/fsl/fslview/displaycontext/volumeopts.py +++ b/fsl/fslview/displaycontext/volumeopts.py @@ -221,7 +221,15 @@ class VolumeOpts(ImageOpts): clippingRange = props.Bounds( ndims=1, labels=[strings.choices['VolumeOpts.displayRange.min'], - strings.choices['VolumeOpts.displayRange.max']]) + strings.choices['VolumeOpts.displayRange.max']]) + """Values outside of this range are not shown.""" + + + invertClipping = props.Boolean(default=False) + """If ``True``, the behaviour of ``clippingRange`` is inverted, i.e. + values inside the clipping range are clipped, instead of those outside + the clipping range. + """ cmap = props.ColourMap(default=fslcm.getColourMaps()[0], diff --git a/fsl/fslview/gl/gl21/glvolume_frag.glsl b/fsl/fslview/gl/gl21/glvolume_frag.glsl index d24efa14d..98e952ca9 100644 --- a/fsl/fslview/gl/gl21/glvolume_frag.glsl +++ b/fsl/fslview/gl/gl21/glvolume_frag.glsl @@ -46,6 +46,12 @@ uniform float clipLow; */ uniform float clipHigh; +/* + * Invert clipping behaviour - clip voxels + * that are inside the clipLow/High bounds. + */ +uniform bool invertClip; + /* * Image voxel coordinates. */ @@ -85,8 +91,9 @@ void main(void) { /* * Clip out of range voxel values */ - if (voxValue < clipLow || voxValue > clipHigh) { + if ((!invertClip && (voxValue < clipLow || voxValue > clipHigh)) || + (invertClip && (voxValue >= clipLow && voxValue <= clipHigh))) { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); return; } diff --git a/fsl/fslview/gl/gl21/glvolume_funcs.py b/fsl/fslview/gl/gl21/glvolume_funcs.py index 47884edcb..502f2e6f7 100644 --- a/fsl/fslview/gl/gl21/glvolume_funcs.py +++ b/fsl/fslview/gl/gl21/glvolume_funcs.py @@ -81,7 +81,9 @@ def compileShaders(self): self.clipLowPos = gl.glGetUniformLocation(self.shaders, 'clipLow') self.clipHighPos = gl.glGetUniformLocation(self.shaders, - 'clipHigh') + 'clipHigh') + self.invertClipPos = gl.glGetUniformLocation(self.shaders, + 'invertClip') def init(self): @@ -130,8 +132,9 @@ def updateShaderState(self): self.imageTexture.invVoxValXform[0, 0] + \ self.imageTexture.invVoxValXform[3, 0] - gl.glUniform1f(self.clipLowPos, clipLow) - gl.glUniform1f(self.clipHighPos, clipHigh) + gl.glUniform1f(self.clipLowPos, clipLow) + gl.glUniform1f(self.clipHighPos, clipHigh) + gl.glUniform1f(self.invertClipPos, opts.invertClipping) # Bind transformation matrices to transform # display coordinates to voxel coordinates, diff --git a/fsl/fslview/gl/glvolume.py b/fsl/fslview/gl/glvolume.py index 183c44eae..b0ba1d940 100644 --- a/fsl/fslview/gl/glvolume.py +++ b/fsl/fslview/gl/glvolume.py @@ -215,18 +215,19 @@ class GLVolume(globject.GLImageObject): fslgl.glvolume_funcs.updateShaderState(self) self.onUpdate() - display.addListener( 'softwareMode', lName, shaderCompile) - display.addListener( 'alpha', lName, colourUpdate) - opts .addListener( 'displayRange', lName, colourUpdate) - opts .addListener( 'clippingRange', lName, shaderUpdate) - opts .addListener( 'cmap', lName, colourUpdate) - opts .addListener( 'invert', lName, colourUpdate) - opts .addListener( 'volume', lName, imageUpdate) - opts .addListener( 'resolution', lName, imageUpdate) - opts .addListener( 'interpolation', lName, imageUpdate) - opts .addSyncChangeListener('volume', lName, imageRefresh) - opts .addSyncChangeListener('resolution', lName, imageRefresh) - opts .addSyncChangeListener('interpolation', lName, imageRefresh) + display.addListener( 'softwareMode', lName, shaderCompile) + display.addListener( 'alpha', lName, colourUpdate) + opts .addListener( 'displayRange', lName, colourUpdate) + opts .addListener( 'clippingRange', lName, shaderUpdate) + opts .addListener( 'invertClipping', lName, shaderUpdate) + opts .addListener( 'cmap', lName, colourUpdate) + opts .addListener( 'invert', lName, colourUpdate) + opts .addListener( 'volume', lName, imageUpdate) + opts .addListener( 'resolution', lName, imageUpdate) + opts .addListener( 'interpolation', lName, imageUpdate) + opts .addSyncChangeListener('volume', lName, imageRefresh) + opts .addSyncChangeListener('resolution', lName, imageRefresh) + opts .addSyncChangeListener('interpolation', lName, imageRefresh) def removeDisplayListeners(self): @@ -239,18 +240,19 @@ class GLVolume(globject.GLImageObject): lName = self.name - display.removeListener( 'softwareMode', lName) - display.removeListener( 'alpha', lName) - opts .removeListener( 'displayRange', lName) - opts .removeListener( 'clippingRange', lName) - opts .removeListener( 'cmap', lName) - opts .removeListener( 'invert', lName) - opts .removeListener( 'volume', lName) - opts .removeListener( 'resolution', lName) - opts .removeListener( 'interpolation', lName) - opts .removeSyncChangeListener('volume', lName) - opts .removeSyncChangeListener('resolution', lName) - opts .removeSyncChangeListener('interpolation', lName) + display.removeListener( 'softwareMode', lName) + display.removeListener( 'alpha', lName) + opts .removeListener( 'displayRange', lName) + opts .removeListener( 'clippingRange', lName) + opts .removeListener( 'invertClipping', lName) + opts .removeListener( 'cmap', lName) + opts .removeListener( 'invert', lName) + opts .removeListener( 'volume', lName) + opts .removeListener( 'resolution', lName) + opts .removeListener( 'interpolation', lName) + opts .removeSyncChangeListener('volume', lName) + opts .removeSyncChangeListener('resolution', lName) + opts .removeSyncChangeListener('interpolation', lName) def preDraw(self): diff --git a/fsl/fslview/layouts.py b/fsl/fslview/layouts.py index d29316164..d718aa608 100644 --- a/fsl/fslview/layouts.py +++ b/fsl/fslview/layouts.py @@ -198,6 +198,7 @@ VolumeOptsLayout = props.VGroup( widget(VolumeOpts, 'interpolation'), widget(VolumeOpts, 'cmap'), widget(VolumeOpts, 'invert'), + widget(VolumeOpts, 'invertClipping'), widget(VolumeOpts, 'displayRange', showLimits=False, slider=True), widget(VolumeOpts, 'clippingRange', showLimits=False, slider=True))) diff --git a/fsl/fslview/luts/random.lut b/fsl/fslview/luts/random.lut new file mode 100644 index 000000000..ec8eb804a --- /dev/null +++ b/fsl/fslview/luts/random.lut @@ -0,0 +1,100 @@ +1 0.753957 0.867576 0.271705 1 +2 0.175670 0.556856 0.853074 2 +3 0.616579 0.428308 0.915121 3 +4 0.110243 0.436278 0.131227 4 +5 0.465684 0.976166 0.635108 5 +6 0.825495 0.771942 0.013743 6 +7 0.628049 0.636244 0.519229 7 +8 0.101028 0.565114 0.029126 8 +9 0.418215 0.220175 0.966078 9 +10 0.816653 0.373931 0.401798 10 +11 0.637509 0.120339 0.753382 11 +12 0.585776 0.032367 0.375861 12 +13 0.015209 0.335977 0.181752 13 +14 0.195217 0.360584 0.037638 14 +15 0.540792 0.393421 0.872021 15 +16 0.100611 0.922189 0.970646 16 +17 0.441413 0.720121 0.114097 17 +18 0.054189 0.802448 0.396482 18 +19 0.843831 0.212114 0.126534 19 +20 0.013238 0.661898 0.627306 20 +21 0.520004 0.060818 0.654433 21 +22 0.961100 0.857134 0.091915 22 +23 0.142877 0.869319 0.327252 23 +24 0.973514 0.177186 0.000637 24 +25 0.193389 0.669488 0.079120 25 +26 0.403754 0.632487 0.672783 26 +27 0.294108 0.238623 0.510592 27 +28 0.024675 0.966545 0.173122 28 +29 0.702642 0.120403 0.836783 29 +30 0.843735 0.511668 0.122329 30 +31 0.247394 0.487522 0.760667 31 +32 0.855482 0.534199 0.062248 32 +33 0.950164 0.137868 0.161542 33 +34 0.878682 0.145550 0.423443 34 +35 0.170771 0.538220 0.479534 35 +36 0.163487 0.638112 0.088006 36 +37 0.309358 0.472614 0.939749 37 +38 0.251450 0.852559 0.238243 38 +39 0.322004 0.339350 0.723849 39 +40 0.073325 0.336263 0.243346 40 +41 0.142180 0.275155 0.774014 41 +42 0.418987 0.583517 0.318479 42 +43 0.995191 0.990123 0.965973 43 +44 0.642541 0.758896 0.143941 44 +45 0.834454 0.761811 0.138111 45 +46 0.501360 0.738872 0.998445 46 +47 0.520952 0.734247 0.817867 47 +48 0.108258 0.250040 0.155309 48 +49 0.325019 0.944486 0.010224 49 +50 0.424140 0.102665 0.490829 50 +51 0.370078 0.800670 0.486968 51 +52 0.065647 0.370630 0.369046 52 +53 0.673859 0.336860 0.451118 53 +54 0.896240 0.208660 0.311405 54 +55 0.032992 0.388272 0.141788 55 +56 0.597351 0.525615 0.506587 56 +57 0.956410 0.771918 0.753641 57 +58 0.120402 0.858108 0.991605 58 +59 0.877427 0.082101 0.234755 59 +60 0.477014 0.491835 0.259360 60 +61 0.542788 0.672746 0.682472 61 +62 0.318897 0.978855 0.982079 62 +63 0.086253 0.190322 0.972290 63 +64 0.312732 0.646115 0.808268 64 +65 0.014660 0.166523 0.833427 65 +66 0.606085 0.568510 0.155079 66 +67 0.012467 0.244901 0.116065 67 +68 0.318608 0.668963 0.480013 68 +69 0.306045 0.464696 0.394668 69 +70 0.379937 0.371335 0.764122 70 +71 0.745970 0.730465 0.745599 71 +72 0.904569 0.522597 0.279317 72 +73 0.217184 0.694758 0.909990 73 +74 0.750476 0.633568 0.058840 74 +75 0.844020 0.863140 0.462612 75 +76 0.281654 0.832169 0.510462 76 +77 0.425268 0.686997 0.222606 77 +78 0.326425 0.540490 0.280333 78 +79 0.590842 0.528112 0.636941 79 +80 0.681903 0.369310 0.461865 80 +81 0.860682 0.849561 0.089141 81 +82 0.619122 0.775355 0.780499 82 +83 0.038706 0.201079 0.453245 83 +84 0.094238 0.713224 0.259966 84 +85 0.179885 0.400481 0.529972 85 +86 0.252183 0.183222 0.057824 86 +87 0.983813 0.054503 0.859952 87 +88 0.762208 0.630860 0.404059 88 +89 0.698418 0.577782 0.759200 89 +90 0.543927 0.277553 0.912846 90 +91 0.716609 0.380220 0.050177 91 +92 0.098866 0.533259 0.482783 92 +93 0.509431 0.652996 0.522129 93 +94 0.703915 0.764983 0.865093 94 +95 0.481741 0.000886 0.392668 95 +96 0.345841 0.333430 0.202012 96 +97 0.950121 0.987155 0.160110 97 +98 0.884708 0.861041 0.278094 98 +99 0.653307 0.993621 0.772908 99 +100 0.670894 0.057756 0.683406 100 \ No newline at end of file -- GitLab