Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various VTK fixes #6559

Merged
merged 5 commits into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions panel/models/vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from ..util import classproperty
from .layout import HTMLBox

vtk_cdn = f"{config.npm_cdn}/vtk.js@20.0.1/vtk.js"
vtk_cdn = f"{config.npm_cdn}/vtk.js@30.1.0/vtk.js"


class VTKAxes(Model):
"""
Expand Down Expand Up @@ -105,7 +106,9 @@ class VTKJSPlot(AbstractVTKPlot):
Bokeh model for plotting a 3D scene saved in the `.vtk-js` format
"""

data = Nullable(String, help="""The serialized vtk.js data""")
data = Nullable(Bytes, help="""The serialized vtk.js data""")

data_url = Nullable(String, help="The data URL")

enable_keybindings = Bool(default=False)

Expand Down
63 changes: 37 additions & 26 deletions panel/models/vtk/vtkjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,39 +33,49 @@ export class VTKJSPlotView extends AbstractVTKView {
}

plot(): void {
if (this.model.data == null) {
if (this.model.data == null && this.model.data_url == null) {
this._vtk_renwin.getRenderWindow().render()
return
}
const dataAccessHelper = vtkns.DataAccessHelper.get("zip", {
zipContent: atob(this.model.data as string),
callback: (_zip: unknown) => {
const sceneImporter = vtkns.HttpSceneLoader.newInstance({
renderer: this._vtk_renwin.getRenderer(),
dataAccessHelper,
})
const fn = (window as any).vtk.macro.debounce(
() => {
setTimeout(() => {
if (this._axes == null && this.model.axes) {
this._set_axes()
}
this._set_camera_state()
this._get_camera_state()
this._vtk_renwin.getRenderWindow().render()
}, 100)
}, 100,
)
sceneImporter.setUrl("index.json")
sceneImporter.onReady(fn)
},
let bytes_promise: any
if (this.model.data_url) {
bytes_promise = vtkns.DataAccessHelper.get("http").fetchBinary(this.model.data_url)
} else {
bytes_promise = async () => { this.model.data }
}
bytes_promise.then((zipContent: ArrayBuffer) => {
const dataAccessHelper = vtkns.DataAccessHelper.get("zip", {
zipContent,
callback: (_zip: unknown) => {
const sceneImporter = vtkns.HttpSceneLoader.newInstance({
renderer: this._vtk_renwin.getRenderer(),
dataAccessHelper,
})
const fn = (window as any).vtk.macro.debounce(
() => {
setTimeout(() => {
if (this._axes == null && this.model.axes) {
this._set_axes()
}
this._set_camera_state()
this._get_camera_state()
this._vtk_renwin.getRenderWindow().render()
}, 100)
}, 100,
)
sceneImporter.setUrl("index.json")
sceneImporter.onReady(fn)
},
})
})
}
}

export namespace VTKJSPlot {
export type Attrs = p.AttrsOf<Props>
export type Props = AbstractVTKPlot.Props
export type Props = AbstractVTKPlot.Props & {
data_url: p.Property<string | null>
}
}

export interface VTKJSPlot extends VTKJSPlot.Attrs {}
Expand All @@ -76,8 +86,9 @@ export class VTKJSPlot extends AbstractVTKPlot {
static {
this.prototype.default_view = VTKJSPlotView

this.define<VTKJSPlot.Props>(({Boolean, Nullable, String}) => ({
data: [ Nullable(String) ],
this.define<VTKJSPlot.Props>(({Boolean, Bytes, Nullable, String}) => ({
data: [ Nullable(Bytes), null ],
data_url: [ Nullable(String), null ],
enable_keybindings: [ Boolean, false ],
}))
}
Expand Down
7 changes: 0 additions & 7 deletions panel/models/vtk/vtklayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,6 @@ export abstract class AbstractVTKView extends HTMLBoxView {
override render(): void {
super.render()
this._rendered = false
if (this._vtk_renwin && this._vtk_container) {
// warning if _vtk_renwin contain controllers or other elements
// we must attach them to the new el
this.shadow_el.appendChild(this._vtk_container)
this.shadow_el.appendChild(this._annotations_container)
return
}
this._orientationWidget = null
this._axes = null
this._vtk_container = div()
Expand Down
35 changes: 19 additions & 16 deletions panel/pane/vtk/vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,33 +841,35 @@ def _get_model(
"""
VTKJSPlot = lazy_load('panel.models.vtk', 'VTKJSPlot', isinstance(comm, JupyterComm), root)
props = self._get_properties(doc)
vtkjs = self._get_vtkjs()
if vtkjs is not None:
props['data'] = base64encode(vtkjs)
props['data_url'], props['data'] = self._get_vtkjs()
model = VTKJSPlot(**props)
root = root or model
self._link_props(model, ['camera', 'enable_keybindings', 'orientation_widget'], doc, root, comm)
self._models[root.ref['id']] = (model, parent)
return model

def _get_vtkjs(self):
def _get_vtkjs(self, fetch=True):
data_path, data_url = None, None
if isinstance(self.object, str) and self.object.endswith('.vtkjs'):
data_path = data_path
if not isfile(self.object):
data_url = self.object
if self._vtkjs is None and self.object is not None:
if isinstance(self.object, str) and self.object.endswith('.vtkjs'):
if isfile(self.object):
with open(self.object, 'rb') as f:
vtkjs = f.read()
else:
data_url = urlopen(self.object)
vtkjs = data_url.read()
vtkjs = None
if data_url and fetch:
vtkjs = urlopen(data_url).read() if fetch else data_url
elif data_path:
with open(self.object, 'rb') as f:
vtkjs = f.read()
elif hasattr(self.object, 'read'):
vtkjs = self.object.read()
self._vtkjs = vtkjs
return self._vtkjs
return data_url, self._vtkjs

def _update(self, ref: str, model: Model) -> None:
self._vtkjs = None
vtkjs = self._get_vtkjs()
model.data = base64encode(vtkjs) if vtkjs is not None else vtkjs
data_url, vtkjs = self._get_vtkjs()
model.update(data_url=data_url, data=vtkjs)

def export_vtkjs(self, filename: str | IO ='vtk_panel.vtkjs'):
"""
Expand All @@ -877,8 +879,9 @@ def export_vtkjs(self, filename: str | IO ='vtk_panel.vtkjs'):
---------
filename: str | IO
"""
_, vtkjs = self._get_vtkjs()
if hasattr(filename, 'write'):
filename.write(self._get_vtkjs())
filename.write(vtkjs)
else:
with open(filename, 'wb') as f:
f.write(self._get_vtkjs())
f.write(vtkjs)
Loading