I would like to use the Figure
object found in BokehJS in @bokeh/bokehjs/build/js/lib/api/plotting.js
for a custom Bokeh extension, however, I cannot figure out the way to add the path to it so that the extension renders in JupyterLab. I am currently using Bokeh version 2.4.3 (for both Python and the JS libraries).
I have updated my tsconfig.json
file to include the path to the module I would like to use, which does not seem to work. Note, all referenced files are below. The bokeh build
command runs without error in the extension directory, but when I load it in a JupyterLab session I get the following error in my browser’s console.
Uncaught Error: Cannot find module '@bokehjs/api/main'
Both the JS and Python files are shown below. Any help regarding how to correctly set up the paths so that I can find the api/plotting.js
module would be greatly appreciated.
files
tsconfig.json
{
"compilerOptions": {
"alwaysStrict": true,
"baseUrl": ".",
"declaration": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"importHelpers": false,
"lib": ["es2020", "dom", "dom.iterable"],
"module": "ES2020",
"moduleResolution": "node",
"noEmitOnError": false,
"noErrorTruncation": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "./dist/lib",
"paths": {
"@bokehjs/*": [
"node_modules/@bokeh/bokehjs/build/js/lib/api/*",
"node_modules/@bokeh/bokehjs/build/js/types/api/*",
"node_modules/@bokeh/bokehjs/build/js/lib/*",
"node_modules/@bokeh/bokehjs/build/js/types/*"
]
},
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strictBindCallApply": false,
"strictFunctionTypes": false,
"strictNullChecks": true,
"strictPropertyInitialization": false,
"target": "ES2020"
},
"include": ["./**/*.ts"]
}
marginal1d.ts
import {HTMLBox, HTMLBoxView} from '@bokehjs/models/layouts/html_box';
import * as p from '@bokehjs/core/properties';
import {ColumnDataSource} from '@bokehjs/models/sources/column_data_source';
import {build_view} from '@bokehjs/core/build_views';
import {div} from '@bokehjs/core/dom';
import * as Bkapi from '@bokehjs/api/main';
const linearRange = (start: number, stop: number, step: number = 1): number[] => {
return Array.from({length: stop - step - start / step + 1}, (_, i) => {
return start + i * step;
});
};
export class Marginal1dView extends HTMLBoxView {
// Declare public writeable properties.
model: Marginal1d;
containerDiv: HTMLDivElement;
plotDiv: HTMLDivElement;
fig: Bkapi.Plotting.Figure;
// Initialize the properties.
initialize(): void {
super.initialize();
this.containerDiv = div({style: 'height: 100%; width: 100%'});
this.plotDiv = div({});
this.containerDiv = div({style: 'height: 100%; width: 100%'}, this.plotDiv);
}
// Render the view.
async render(): Promise<void> {
super.render();
this.el.appendChild(this.containerDiv);
await this.setPlot();
}
private async setPlot() {
// Compute the data for the initial view
const x = linearRange(0, 300, 10);
const y: number[] = [];
for (let i = 0; i < x.length; i += 1) {
y.push(Math.sin(x[i]));
}
// Create the source for the initial view
const source = new ColumnDataSource({data: {x: x, y: y}});
// Create the figures
this.fig = new Bkapi.Plotting.Figure({
background_fill_color: null,
border_fill_color: null,
outline_line_color: null,
min_border: 0,
sizing_mode: 'stretch_both',
toolbar_location: null,
});
// Add the glyphs to the figure
this.fig.line({
x: {field: 'x'},
y: {field: 'y'},
source: source,
});
// Render the figure
const view = await build_view(this.fig);
this.plotDiv.innerHTML = '';
view.renderTo(this.plotDiv);
}
}
export namespace Marginal1d {
export type Attrs = p.AttrsOf<Props>;
export type Props = HTMLBox.Props;
}
export interface Marginal1d extends Marginal1d.Attrs {}
export class Marginal1d extends HTMLBox {
properties: Marginal1d.Props;
__view_type__: Marginal1dView;
static __module__ = 'diagnostics.bokeh_extensions.marginal1d';
constructor(attrs?: Partial<Marginal1d.Attrs>) {
super(attrs);
}
static {
this.prototype.default_view = Marginal1dView;
}
}
marginal1d.py
from bokeh.models import HTMLBox
class Marginal1d(HTMLBox):
pass