Hi,
I was looking at this example for wrapping a js library: Wrapping a JavaScript library — Bokeh 2.4.2 Documentation
Not entirely sure about the TS part of the code. If I wanted to use something like this:
https://visjs.github.io/vis-network/examples/
I tried something like this (getting a ton of errors):
import numpy as np
from bokeh.core.properties import Instance, String
from bokeh.io import show
from bokeh.models import ColumnDataSource, LayoutDOM
from bokeh.util.compiler import TypeScript
TS_CODE = """
import {LayoutDOM, LayoutDOMView} from "models/layouts/layout_dom"
import {ColumnDataSource} from "models/sources/column_data_source"
import {LayoutItem} from "core/layout"
import * as p from "core/properties"
declare namespace vis {
class Network {
constructor(el: HTMLElement, data: object, OPTIONS: object)
setData(data: vis.DataSet): void
}
class DataSet {
add(data: unknown): void
}
}
const OPTIONS = {
nodes: {
shape: "dot",
size: 16
},
layout: {
randomSeed: 34
},
physics: {
forceAtlas2Based: {
gravitationalConstant: -26,
centralGravity: 0.005,
springLength: 230,
springConstant: 0.18
},
maxVelocity: 146,
solver: "forceAtlas2Based",
timestep: 0.35,
stabilization: {
enabled: true,
iterations: 2000,
updateInterval: 25
}
}
}
export class Network extends LayoutDOMView {
model: Network
private _graph: vis.Network
initialize(): void {
super.initialize()
const url = "https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.js"
const script = document.createElement("script")
script.onload = () => this._init()
script.async = false
script.src = url
document.head.appendChild(script)
}
private _init(): void {
this._graph = new vis.Network(this.el, this.get_data(), OPTIONS)
this.connect(this.model.data_source.change, () => {
this._graph.setData(this.get_data())
})
}
get_data(): vis.DataSet {
const data = new vis.DataSet()
const source = this.model.data_source
for (let i = 0; i < source.get_length()!; i++) {
data.add({
nodes: source.data[this.model.nodes][i],
egdes: source.data[this.model.egdes][i],
})
}
return data
}
get child_models(): LayoutDOM[] {
return []
}
_update_layout(): void {
this.layout = new LayoutItem()
this.layout.set_sizing(this.box_sizing())
}
}
export namespace Network {
export type Attrs = p.AttrsOf<Props>
export type Props = LayoutDOM.Props & {
nodes: p.Property<string>
egdes: p.Property<string>
data_source: p.Property<ColumnDataSource>
}
}
export interface Network extends Network.Attrs {}
export class Network extends LayoutDOM {
properties: Network.Props
constructor(attrs?: Partial<Network.Attrs>) {
super(attrs)
}
static __name__ = "Network"
static init_Network() {
this.prototype.default_view = NetworkView
this.define<Network.Props>({
nodes: [ p.String ],
egdes: [ p.String ],
data_source: [ p.Instance ],
})
}
}
"""
# This custom extension model will have a DOM view that should layout-able in
# Bokeh layouts, so use ``LayoutDOM`` as the base class. If you wanted to create
# a custom tool, you could inherit from ``Tool``, or from ``Glyph`` if you
# wanted to create a custom glyph, etc.
class Network(LayoutDOM):
# The special class attribute ``__implementation__`` should contain a string
# of JavaScript code that implements the browser side of the extension model.
__implementation__ = TypeScript(TS_CODE)
# Below are all the "properties" for this model. Bokeh properties are
# class attributes that define the fields (and their types) that can be
# communicated automatically between Python and the browser. Properties
# also support type validation. More information about properties in
# can be found here:
#
# https://docs.bokeh.org/en/latest/docs/reference/core/properties.html#bokeh-core-properties
# This is a Bokeh ColumnDataSource that can be updated in the Bokeh
# server by Python code
data_source = Instance(ColumnDataSource)
# The vis.js library that we are wrapping expects data for x, y, and z.
# The data will actually be stored in the ColumnDataSource, but these
# properties let us specify the *name* of the column that should be
# used for each field.
nodes = String
edges = String
nodes = np.arange(0, 300, 10)
egdes = np.arange(0, 300, 10)
source = ColumnDataSource(data=dict(nodes=nodes, egdes=egdes))
surface = Network(nodes="nodes", edges="edges", data_source=source, width=600, height=600)
show(surface)