8000 Vtk/vtk improvements (#2826) · holoviz/panel@b0d9b5a · GitHub
[go: up one dir, main page]

Skip to content

Commit b0d9b5a

Browse files
Vtk/vtk improvements (#2826)
* dead code, bokeh define syntax, code formatting * nan opacity volume slices and update vtkjs * add some delete in remove model * Update panel/models/vtk/vtkvolume.ts * document nan opacity Co-authored-by: ARTUSI <xavier.artusi@cea.fr> Co-authored-by: Philipp Rudiger <prudiger@anaconda.com>
1 parent 30843db commit b0d9b5a

File tree

7 files changed

+55
-35
lines changed

7 files changed

+55
-35
lines changed

examples/reference/panes/VTK.ipynb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,9 @@
286286
" \"\"\"Given an array of points, make a line set\"\"\"\n",
287287
" poly = pv.PolyData()\n",
288288
" poly.points = points\n",
289-
" cells = np.full((len(points)-1, 3), 2, dtype=np.int)\n",
290-
" cells[:, 1] = np.arange(0, len(points)-1, dtype=np.int)\n",
291-
" cells[:, 2] = np.arange(1, len(points), dtype=np.int)\n",
289+
" cells = np.full((len(points)-1, 3), 2, dtype=np.int32)\n",
290+
" cells[:, 1] = np.arange(0, len(points)-1, dtype=np.int32)\n",
291+
" cells[:, 2] = np.arange(1, len(points), dtype=np.int32)\n",
292292
" poly.lines = cells\n",
293293
" return poly\n",
294294
"\n",
@@ -436,7 +436,9 @@
436436
"metadata": {
437437
"language_info": {
438438
"name": "python",
439-
"pygments_lexer": "ipython3"
439+
"nbconvert_exporter": "python",
440+
"pygments_lexer": "ipython3",
441+
"version": "3.8.6"
440442
}
441443
},
442444
"nbformat": 4,

examples/reference/panes/VTKVolume.ipynb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
"* **``slice_j``** (Integer): parameter to control the position of the slice normal to the Y direction. By default the the value is computed to be in the middle of the data\n",
7474
"\n",
7575
"* **``slice_k``** (Integer): parameter to control the position of the slice normal to the Z direction. By default the the value is computed to be in the middle of the data\n",
76+
"\n",
77+
"* **``nan_opacity``** (Number): parameter to control the opacity of NaN values in a slice. By default the the value is 1. The value must be in (0, 1)\n",
7678
"___"
7779
]
7880
},

panel/models/vtk.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from ..io.resources import bundled_files
1414
from ..util import classproperty
1515

16-
vtk_cdn = "https://unpkg.com/vtk.js@14.16.4/dist/vtk.js"
16+
vtk_cdn = "https://unpkg.com/vtk.js@20.0.1/vtk.js"
1717

1818
class VTKAxes(Model):
1919
"""
@@ -135,6 +135,8 @@ class VTKVolumePlot(AbstractVTKPlot):
135135

136136
mapper = Dict(String, Any)
137137

138+
nan_opacity = Float(default=1)
139+
138140
render_background = String(default='#52576e')
139141

140142
rescale = Bool(default=False)

panel/models/vtk/vtklayout.ts

Lines changed: 3 additions & 1 deletion
Original file line numb EDB7 erDiff line numberDiff line change
@@ -88,7 +88,7 @@ export abstract class AbstractVTKView extends PanelHTMLBoxView {
8888

8989
info_div.click()
9090
}
91-
91+
9292
_init_annotations_container(): void {
9393
if (!this._annotations_container) {
9494
this._annotations_container = document.createElement("div")
@@ -237,6 +237,8 @@ export abstract class AbstractVTKView extends PanelHTMLBoxView {
237237
remove(): void {
238238
this._unsubscribe_camera_cb()
239239
window.removeEventListener("resize", this._vtk_renwin.resize)
240+
if (this._orientationWidget!=null) this._orientationWidget.delete()
241+
this._vtk_renwin.getRenderWindow().getInteractor().delete()
240242
this._vtk_renwin.delete()
241243
super.remove()
242244
}

panel/models/vtk/vtksynchronized.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as p from "@bokehjs/core/properties"
2-
import { clone } from "@bokehjs/core/util/object"
2+
import {clone} from "@bokehjs/core/util/object"
33

44
import {AbstractVTKView, AbstractVTKPlot} from "./vtklayout"
55

@@ -16,7 +16,6 @@ export class VTKSynchronizedPlotView extends AbstractVTKView {
1616
protected _decoded_arrays: any
1717
protected _pending_arrays: any
1818
protected _promises: Promise<any>[]
19-
public getArray: CallableFunction
2019
public registerArray: CallableFunction
2120

2221
initialize(): void {
@@ -26,16 +25,7 @@ export class VTKSynchronizedPlotView extends AbstractVTKView {
2625
this._arrays = {}
2726
this._decoded_arrays = {}
2827
this._pending_arrays = {}
29-
// Internal closures
30-
this.getArray = (hash: string) => {
31-
if (this._arrays[hash]) {
32-
return Promise.resolve(this._arrays[hash])
33-
}
3428

35-
return new Promise((resolve, reject) => {
36-
this._pending_arrays[hash] = {resolve, reject}
37-
})
38-
}
3929

4030
this.registerArray = (hash: string, array: any) => {
4131
this._arrays[hash] = array
@@ -106,7 +96,7 @@ export class VTKSynchronizedPlotView extends AbstractVTKView {
10696
.loadAsync(atob(arrays[key]))
10797
.then((zip: any) => zip.file("data/" + key))
10898
.then((zipEntry: any) => zipEntry.async("arraybuffer"))
109-
.then((arraybuffer: any) => registerArray(key, arraybuffer))
99+
.then((arraybuffer: any) => registerArray(key, arraybuffer))
110100
.then(() => {
111101
arrays_processed.push(key)
112102
model.properties.arrays_processed.change.emit()
@@ -200,14 +190,14 @@ export class VTKSynchronizedPlot extends AbstractVTKPlot {
200190
static init_VTKSynchronizedPlot(): void {
201191
this.prototype.default_view = VTKSynchronizedPlotView
202192

203-
this.define<VTKSynchronizedPlot.Props>({
204-
arrays: [ p.Any, {} ],
205-
arrays_processed: [ p.Array, [] ],
206-
enable_keybindings: [ p.Boolean, false ],
207-
one_time_reset: [ p.Boolean ],
208-
rebuild: [ p.Boolean, false ],
209-
scene: [ p.Any, {} ],
210-
})
193+
this.define<VTKSynchronizedPlot.Props>(({Any, Array, Boolean, String}) => ({
194+
arrays: [ Any, {} ],
195+
arrays_processed: [ Array(String), [] ],
196+
enable_keybindings: [ Boolean, false ],
197+
one_time_reset: [ Boolean ],
198+
rebuild: [ Boolean, false ],
199+
scene: [ Any, {} ],
200+
}))
211201

212202
this.override<VTKSynchronizedPlot.Props>({
213203
height: 300,

panel/models/vtk/vtkvolume.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ export class VTKVolumePlotView extends AbstractVTKView {
103103
if (this._controllerWidget != null)
104104
this._controllerWidget.setExpanded(this.model.controller_expanded)
105105
})
106+
this.connect(this.model.properties.nan_opacity.change, () => {
107+
const scalar_opacity = this.image_actor_i.getProperty().getScalarOpacity()
108+
scalar_opacity.get(["nodes"]).nodes[0].y = this.model.nan_opacity
109+
scalar_opacity.modified()
110+
this._vtk_renwin.getRenderWindow().render()
111+
})
106112
}
107113

108114
render(): void {
@@ -263,9 +269,13 @@ export class VTKVolumePlotView extends AbstractVTKView {
263269

264270
// set_color and opacity
265271
const piecewiseFunction = vtkns.PiecewiseFunction.newInstance()
266-
piecewiseFunction.removeAllPoints()
267-
piecewiseFunction.addPoint(0, 1)
268272
const lookupTable = this.volume.getProperty().getRGBTransferFunction(0)
273+
const range = this.volume.getMapper().getInputData().getPointData().getScalars().getRange()
274+
piecewiseFunction.removeAllPoints()
275+
piecewiseFunction.addPoint(range[0]-1, this.model.nan_opacity)
276+
piecewiseFunction.addPoint(range[0], 1)
277+
piecewiseFunction.addPoint(range[1], 1)
278+
269279
const property = image_actor_i.getProperty()
270280
image_actor_j.setProperty(property)
271281
image_actor_k.setProperty(property)
@@ -360,10 +370,9 @@ export class VTKVolumePlotView extends AbstractVTKView {
360370
}
361371

362372
_set_slices_visibility(visibility: boolean): void {
363-
this._vtk_renwin
364-
.getRenderer()
365-
.getActors()
366-
.map((actor: any) => actor.setVisibility(visibility) 627F )
373+
this.image_actor_i.setVisibility(visibility)
374+
this.image_actor_j.setVisibility(visibility)
375+
this.image_actor_k.setVisibility(visibility)
367376
}
368377

369378
_set_volume_visibility(visibility: boolean): void {
@@ -382,6 +391,7 @@ export namespace VTKVolumePlot {
382391
edge_gradient: p.Property<number>
383392
interpolation: p.Property<Interpolation>
384393
mapper: p.Property<ColorMapper>
394+
nan_opacity: p.Property<number>
385395
render_background: p.Property<string>
386396
rescale: p.Property<boolean>
387397
sampling: p.Property<number>
@@ -417,6 +427,7 @@ export class VTKVolumePlot extends AbstractVTKPlot {
417427
edge_gradient: [ Number, 0.2 ],
418428
interpolation: [ Interpolation, 'fast_linear'],
419429
mapper: [ Struct({palette: Array(String), low: Number, high: Number}) ],
430+
nan_opacity: [ Number, 1 ],
420431
render_background: [ String, '#52576e' ],
421432
rescale: [ Boolean, false ],
422433
sampling: [ Number, 0.4 ],

panel/pane/vtk/vtk.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,15 @@ def unlink_camera(self):
482482
old_camera = self.vtk_camera
483483
new_camera = vtk.vtkCamera()
484484
self.vtk_camera = new_camera
485-
exclude_properties = ['mtime']
485+
exclude_properties = [
486+
'mtime',
487+
'projectionMatrix',
488+
'viewMatrix',
489+
'physicalTranslation',
490+
'physicalScale',
491+
'physicalViewUp',
492+
'physicalViewNorth'
493+
]
486494
if self.camera is not None:
487495
for k, v in self.camera.items():
488496
if k not in exclude_properties:
@@ -539,6 +547,9 @@ class VTKVolume(AbstractVTK):
539547
max_data_size = param.Number(default=(256 ** 3) * 2 / 1e6, doc="""
540548
Maximum data size transfert allowed without subsampling""")
541549

550+
nan_opacity = param.Number(default=1., bounds=(0., 1.), doc="""
551+
Opacity applied to nan values in slices""")
552+
542553
origin = param.Tuple(default=None, length=3, allow_None=True)
543554

544555
render_background = param.Color(default='#52576e', doc="""
@@ -617,7 +628,7 @@ def _get_model(self, doc, root=None, parent=None, comm=None):
617628
model = VTKVolumePlot(**props)
618629
if root is None:
619630
root = model
620-
self._link_props(model, ['colormap', 'orientation_widget', 'camera', 'mapper', 'controller_expanded'], doc, root, comm)
631+
self._link_props(model, ['colormap', 'orientation_widget', 'camera', 'mapper', 'controller_expanded', 'nan_opacity'], doc, root, comm)
621632
self._models[root.ref['id']] = (model, parent)
622633
return model
623634

@@ -683,7 +694,7 @@ def _volume_from_array(self, sub_array):
683694
dims=sub_array.shape,
684695
spacing=self._sub_spacing,
685696
origin=self.origin,
686-
data_range=(sub_array.min(), sub_array.max()),
697+
data_range=(np.nanmin(sub_array), np.nanmax(sub_array)),
687698
dtype=sub_array.dtype.name)
688699

689700
def _get_volume_data(self):

0 commit comments

Comments
 (0)
0