Skip to content

Commit

Permalink
ENH: Expose image slicing plane positions as traits
Browse files Browse the repository at this point in the history
  • Loading branch information
thewtex committed Jan 15, 2020
1 parent 17c6810 commit 3dbc815
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 15 deletions.
39 changes: 28 additions & 11 deletions itkwidgets/widget_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,29 +131,37 @@ class Viewer(ViewerParent):
**itkimage_serialization)
_rendering_image = CBool(
default_value=False,
help="We are currently volume rendering the image.").tag(
sync=True)
help="We are currently volume rendering the image.").tag(sync=True)
interpolation = CBool(
default_value=True,
help="Use linear interpolation in slicing planes.").tag(
sync=True)
help="Use linear interpolation in slicing planes.").tag(sync=True)
cmap = Colormap('Viridis (matplotlib)').tag(sync=True)
_custom_cmap = NDArray(dtype=np.float32, default_value=None, allow_none=True,
help="RGB triples from 0.0 to 1.0 that define a custom linear, sequential colormap")\
.tag(sync=True, **array_serialization)\
.valid(shape_constraints(None, 3))
shadow = CBool(
default_value=True,
help="Use shadowing in the volume rendering.").tag(
sync=True)
help="Use shadowing in the volume rendering.").tag(sync=True)
slicing_planes = CBool(
default_value=False,
help="Display the slicing planes in volume rendering view mode.").tag(
sync=True)
x_slice = CFloat(
default_value=None,
allow_none=True,
help="World-space position of the X slicing plane.").tag(sync=True)
y_slice = CFloat(
default_value=None,
allow_none=True,
help="World-space position of the Y slicing plane.").tag(sync=True)
z_slice = CFloat(
default_value=None,
allow_none=True,
help="World-space position of the Z slicing plane.").tag(sync=True)
gradient_opacity = CFloat(
default_value=0.2,
help="Volume rendering gradient opacity, from (0.0, 1.0]").tag(
sync=True)
help="Volume rendering gradient opacity, from (0.0, 1.0]").tag(sync=True)
blend = CaselessStrEnum(
('composite',
'max',
Expand Down Expand Up @@ -640,15 +648,24 @@ def view(image=None, # noqa: C901
select_roi: bool, optional, default: False
Enable an interactive region of interest widget for the image.
slicing_planes: bool, optional, default: False
Enable slicing planes on the volume rendering.
x_slice: float, optional, default: None
World-space position of the X slicing plane.
y_slice: float, optional, default: None
World-space position of the Y slicing plane.
z_slice: float, optional, default: None
World-space position of the Z slicing plane.
interpolation: bool, optional, default: True
Linear as opposed to nearest neighbor interpolation for image slices.
gradient_opacity: float, optional, default: 0.22
Gradient opacity for composite volume rendering, in the range (0.0, 1.0].
slicing_planes: bool, optional, default: False
Enable slicing planes on the volume rendering.
shadow: bool, optional, default: True
Use shadowing with composite volume rendering.
Expand Down
64 changes: 64 additions & 0 deletions js/lib/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ const ViewerModel = widgets.DOMWidgetModel.extend({
vmax: null,
shadow: true,
slicing_planes: false,
x_slice: null,
y_slice: null,
z_slice: null,
gradient_opacity: 0.2,
blend: 'composite',
roi: new Float64Array([0., 0., 0., 0., 0., 0.]),
Expand Down Expand Up @@ -494,6 +497,9 @@ const ViewerView = widgets.DOMWidgetView.extend({
if (rendered_image) {
this.shadow_changed()
this.slicing_planes_changed()
this.x_slice_changed()
this.y_slice_changed()
this.z_slice_changed()
this.gradient_opacity_changed()
this.blend_changed()
}
Expand Down Expand Up @@ -674,6 +680,40 @@ const ViewerView = widgets.DOMWidgetView.extend({
}
this.model.itkVtkViewer.subscribeToggleSlicingPlanes(onSlicingPlanesToggle)

const onXSliceChanged = (position) => {
if (position !== this.model.get('x_slice')) {
this.model.set('x_slice', position)
this.model.save_changes()
}
}
this.model.itkVtkViewer.subscribeXSliceChanged(onXSliceChanged)
if (this.model.get('x_slice') === null) {
this.model.set('x_slice', this.model.itkVtkViewer.getXSlice())
this.model.save_changes()
}
const onYSliceChanged = (position) => {
if (position !== this.model.get('y_slice')) {
this.model.set('y_slice', position)
this.model.save_changes()
}
}
this.model.itkVtkViewer.subscribeYSliceChanged(onYSliceChanged)
if (this.model.get('y_slice') === null) {
this.model.set('y_slice', this.model.itkVtkViewer.getYSlice())
this.model.save_changes()
}
const onZSliceChanged = (position) => {
if (position !== this.model.get('z_slice')) {
this.model.set('z_slice', position)
this.model.save_changes()
}
}
this.model.itkVtkViewer.subscribeZSliceChanged(onZSliceChanged)
if (this.model.get('z_slice') === null) {
this.model.set('z_slice', this.model.itkVtkViewer.getZSlice())
this.model.save_changes()
}

const onGradientOpacityChange = (opacity) => {
if (opacity !== this.model.get('gradient_opacity')) {
this.model.set('gradient_opacity', opacity)
Expand Down Expand Up @@ -706,6 +746,9 @@ const ViewerView = widgets.DOMWidgetView.extend({
this.model.on('change:vmax', this.vmax_changed, this)
this.model.on('change:shadow', this.shadow_changed, this)
this.model.on('change:slicing_planes', this.slicing_planes_changed, this)
this.model.on('change:x_slice', this.x_slice_changed, this)
this.model.on('change:y_slice', this.y_slice_changed, this)
this.model.on('change:z_slice', this.z_slice_changed, this)
this.model.on('change:gradient_opacity', this.gradient_opacity_changed, this)
this.model.on('change:blend', this.blend_changed, this)
this.model.on('change:select_roi', this.select_roi_changed, this)
Expand Down Expand Up @@ -1040,6 +1083,27 @@ const ViewerView = widgets.DOMWidgetView.extend({
}
},

x_slice_changed: function() {
const position = this.model.get('x_slice')
if (this.model.hasOwnProperty('itkVtkViewer') && !this.model.use2D && position !== null) {
this.model.itkVtkViewer.setXSlice(position)
}
},

y_slice_changed: function() {
const position = this.model.get('y_slice')
if (this.model.hasOwnProperty('itkVtkViewer') && !this.model.use2D && position !== null) {
this.model.itkVtkViewer.setYSlice(position)
}
},

z_slice_changed: function() {
const position = this.model.get('z_slice')
if (this.model.hasOwnProperty('itkVtkViewer') && !this.model.use2D && position !== null) {
this.model.itkVtkViewer.setZSlice(position)
}
},

gradient_opacity_changed: function() {
const gradient_opacity = this.model.get('gradient_opacity')
if (this.model.hasOwnProperty('itkVtkViewer') && !this.model.use2D) {
Expand Down
6 changes: 3 additions & 3 deletions js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"copy-webpack-plugin": "^4.5.1",
"css-element-queries": "^1.0.2",
"itk": "^10.2.0",
"itk-vtk-viewer": "^9.10.4",
"itk-vtk-viewer": "^9.11.0",
"jupyter-dataserializers": "^2.1.0",
"mobx": "^5.13.0",
"vtk.js": "^13.0.0"
Expand Down

0 comments on commit 3dbc815

Please sign in to comment.