Skip to content
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
10 changes: 5 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ workflows:
visual-tests:
jobs:
- visual:
name: << matrix.jobname >>
matrix:
parameters:
jobname:
- "py311-visual"
name: py311-bqplot012-visual
jobname: py311-bqplot012-visual
- visual:
name: py311-bqplot013-visual
jobname: py311-bqplot013-visual
6 changes: 3 additions & 3 deletions js/lib/BrushEllipseSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const BaseXYSelector = __importStar(require("bqplot")).BaseXYSelector;
const d3 = require("d3");
const d3_drag_1 = require("d3-drag");
const d3Selection = require("d3-selection");
const { applyStyles } = require("./utils");
const { applyStyles, setRange } = require("./utils");
const d3GetEvent = function () { return require("d3-selection").event; }.bind(this);
/*
good resource: https://en.wikipedia.org/wiki/Ellipse
Expand Down Expand Up @@ -198,8 +198,8 @@ class BrushEllipseSelector extends BaseXYSelector {
}
relayout() {
super.relayout();
this.x_scale.set_range(this.parent.padded_range("x", this.x_scale.model));
this.y_scale.set_range(this.parent.padded_range("y", this.y_scale.model));
setRange(this.x_scale, this.parent.padded_range("x", this.x_scale.model));
setRange(this.y_scale, this.parent.padded_range("y", this.y_scale.model));
// Called when the figure margins are updated.
this.eventElement
.attr("width", this.parent.width -
Expand Down
6 changes: 3 additions & 3 deletions js/lib/BrushRectangleSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const BaseXYSelector = __importStar(require("bqplot")).BaseXYSelector;
const d3 = require("d3");
const d3_drag_1 = require("d3-drag");
const d3Selection = require("d3-selection");
const { applyStyles } = require("./utils");
const { applyStyles, setRange } = require("./utils");
const d3GetEvent = function () { return require("d3-selection").event; }.bind(this);

class BrushRectangleSelector extends BaseXYSelector {
Expand Down Expand Up @@ -189,8 +189,8 @@ class BrushRectangleSelector extends BaseXYSelector {
}
relayout() {
super.relayout();
this.x_scale.set_range(this.parent.padded_range("x", this.x_scale.model));
this.y_scale.set_range(this.parent.padded_range("y", this.y_scale.model));
setRange(this.x_scale, this.parent.padded_range("x", this.x_scale.model));
setRange(this.y_scale, this.parent.padded_range("y", this.y_scale.model));
// Called when the figure margins are updated.
this.eventElement
.attr("width", this.parent.width -
Expand Down
5 changes: 3 additions & 2 deletions js/lib/MouseInteraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const d3 = require("d3");
const d3_drag_1 = require("d3-drag");
const _ = require("lodash");
const d3_selection_1 = require("d3-selection");
const { setRange } = require("./utils");
const d3GetEvent = function () { return require("d3-selection").event || window.event; }.bind(this);

const clickEvents = ['click', 'dblclick', 'mouseenter', 'mouseleave', 'contextmenu'];
Expand Down Expand Up @@ -208,8 +209,8 @@ class MouseInteraction extends Interaction_1.Interaction {
}

updateScaleRanges() {
this.x_scale.set_range(this.parent.padded_range("x", this.x_scale.model));
this.y_scale.set_range(this.parent.padded_range("y", this.y_scale.model));
setRange(this.x_scale, this.parent.padded_range("x", this.x_scale.model));
setRange(this.y_scale, this.parent.padded_range("y", this.y_scale.model));
}
remove() {
super.remove();
Expand Down
17 changes: 17 additions & 0 deletions js/lib/bqplot-gl-loader-classic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
function loadBqplotGL() {
// Classic widget frontends load nbextensions through RequireJS. Keeping
// this AMD-only prevents bqplot 0.12 from fetching bqplot-gl eagerly.
var amdRequire = typeof window !== "undefined" && (window.requirejs || window.require);
if(!amdRequire) {
return Promise.reject(new Error("bqplot-image-gl with bqplot 0.13 requires bqplot-gl. Install and enable bqplot-gl, or use bqplot 0.12."));
}
return new Promise((resolve, reject) => {
amdRequire(["bqplot-gl"], resolve, () => {
reject(new Error("bqplot-image-gl with bqplot 0.13 requires bqplot-gl. Install and enable bqplot-gl, or use bqplot 0.12."));
});
});
}

export {
loadBqplotGL
};
11 changes: 11 additions & 0 deletions js/lib/bqplot-gl-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function loadBqplotGL() {
// JupyterLab 4 resolves separately installed widget packages through
// module federation, so the labextension bundle must use dynamic import.
return import("bqplot-gl").catch(() => {
throw new Error("bqplot-image-gl with bqplot 0.13 requires bqplot-gl. Install and enable bqplot-gl, or use bqplot 0.12.");
});
}

export {
loadBqplotGL
};
76 changes: 76 additions & 0 deletions js/lib/compat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
var {loadBqplotGL} = require("./bqplot-gl-loader");

function is_bqplot_013_figure(fig) {
return Boolean(fig.extras);
}

function get_bqplot_012_plotarea(fig) {
return {
width: fig.plotarea_width,
height: fig.plotarea_height,
};
}

function get_bqplot_013_plotarea(fig) {
return {
width: fig.plotareaWidth,
height: fig.plotareaHeight,
};
}

function register_bqplot_013_webgl_mark(mark_view) {
var marks = mark_view.parent.extras && mark_view.parent.extras.webGLMarks;
if(marks && marks.indexOf(mark_view) === -1) {
marks.push(mark_view);
}
}

function ensure_bqplot_013_webgl_figure(mark_view) {
var fig = mark_view.parent;
if(!is_bqplot_013_figure(fig)) {
return Promise.resolve();
}
if(fig.extras.webGLRequestRender) {
register_bqplot_013_webgl_mark(mark_view);
return Promise.resolve();
}
return loadBqplotGL().then((bqplot_gl) => {
if(!bqplot_gl.initializeBqplotFigure) {
throw new Error("bqplot-gl did not export initializeBqplotFigure.");
}
bqplot_gl.initializeBqplotFigure(fig);
register_bqplot_013_webgl_mark(mark_view);
});
}

function request_bqplot_012_webgl_render(fig) {
if(fig.update_gl) {
fig.update_gl();
}
}

function request_bqplot_013_webgl_render(fig) {
if(fig.extras.webGLRequestRender) {
fig.extras.webGLRequestRender();
}
// bqplot 0.13 creates Figure.extras before bqplot-gl has installed
// the request-render hook; early draw calls during super.render()
// are replayed after initialization.
}

function request_webgl_render(mark_view) {
var fig = mark_view.parent;
if(is_bqplot_013_figure(fig)) {
request_bqplot_013_webgl_render(fig);
} else {
request_bqplot_012_webgl_render(fig);
}
}

export {
ensure_bqplot_013_webgl_figure,
get_bqplot_012_plotarea,
get_bqplot_013_plotarea,
is_bqplot_013_figure,
request_webgl_render,
};
14 changes: 8 additions & 6 deletions js/lib/contour.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as d3contour from "d3-contour";
import * as d3geo from "d3-geo";
import * as d3 from "d3";
import * as jupyter_dataserializers from "jupyter-dataserializers";
import {colorRange, domain, setRange} from "./utils";


class ContourModel extends bqplot.MarkModel {
Expand Down Expand Up @@ -141,12 +142,13 @@ class ContourView extends bqplot.Mark {
return color_array[index % color_array.length];
}
const model = this.model;
var colors = this.scales.image.model.color_range;
var colors = colorRange(this.scales.image.model);
var color_domain = domain(this.scales.image.model);
var color_scale = d3.scaleLinear()
.range(colors)
.domain(this.scales.image.model.domain);
const min = this.scales.image.model.domain[0];
const max = this.scales.image.model.domain[this.scales.image.model.domain.length-1];
.domain(color_domain);
const min = color_domain[0];
const max = color_domain[color_domain.length-1];
const delta = max - min;
// a good default color is one that is 50% off from the value of the colormap
const level_plus_50_percent = ((threshold - min) + delta / 2) % delta + min;
Expand Down Expand Up @@ -179,10 +181,10 @@ class ContourView extends bqplot.Mark {
var x_scale = this.scales.x,
y_scale = this.scales.y;
if(x_scale) {
x_scale.set_range(this.parent.padded_range("x", x_scale.model));
setRange(x_scale, this.parent.padded_range("x", x_scale.model));
}
if(y_scale) {
y_scale.set_range(this.parent.padded_range("y", y_scale.model));
setRange(y_scale, this.parent.padded_range("y", y_scale.model));
}
}
draw() {
Expand Down
63 changes: 43 additions & 20 deletions js/lib/imagegl.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ var _ = require('lodash');
var d3 = require("d3");
var bqplot = require('bqplot');
var THREE = require('three');
var {colorRange, computeAndSetDomain, delDomain, setRange} = require('./utils');
var {
ensure_bqplot_013_webgl_figure,
get_bqplot_012_plotarea,
get_bqplot_013_plotarea,
request_webgl_render,
} = require("./compat");

var interpolations = {'nearest': THREE.NearestFilter, 'bilinear': THREE.LinearFilter};

Expand Down Expand Up @@ -51,7 +58,7 @@ class ImageGLModel extends bqplot.MarkModel {
close(comm_closed) {
const image = this.get("image");
if(image.image && image.image.src) {
URL.revokeObjectURL(previous.image.src);
URL.revokeObjectURL(image.image.src);
}
return super.close(comm_closed);
}
Expand All @@ -74,16 +81,16 @@ class ImageGLModel extends bqplot.MarkModel {

if(x_scale) {
if(!this.get("preserve_domain").x) {
x_scale.compute_and_set_domain(this.mark_data.x, this.model_id + "_x");
computeAndSetDomain(x_scale, this.mark_data.x, this.model_id + "_x");
} else {
x_scale.del_domain([], this.model_id + "_x");
delDomain(x_scale, [], this.model_id + "_x");
}
}
if(y_scale) {
if(!this.get("preserve_domain").y) {
y_scale.compute_and_set_domain(this.mark_data.y, this.model_id + "_y");
computeAndSetDomain(y_scale, this.mark_data.y, this.model_id + "_y");
} else {
y_scale.del_domain([], this.model_id + "_y");
delDomain(y_scale, [], this.model_id + "_y");
}
}
}
Expand Down Expand Up @@ -176,7 +183,7 @@ class ImageGLView extends bqplot.Mark {
this.scene = new THREE.Scene();
this.scene.add(this.image_mesh);

return base_render_promise.then(() => {
return base_render_promise.then(() => ensure_bqplot_013_webgl_figure(this)).then(() => {
this.create_listeners();
this.update_minmax();
this.update_colormap();
Expand Down Expand Up @@ -209,10 +216,10 @@ class ImageGLView extends bqplot.Mark {
var x_scale = this.scales.x,
y_scale = this.scales.y;
if(x_scale) {
x_scale.set_range(this.parent.padded_range("x", x_scale.model));
setRange(x_scale, this.parent.padded_range("x", x_scale.model));
}
if(y_scale) {
y_scale.set_range(this.parent.padded_range("y", y_scale.model));
setRange(y_scale, this.parent.padded_range("y", y_scale.model));
}
}

Expand Down Expand Up @@ -293,7 +300,7 @@ class ImageGLView extends bqplot.Mark {
}

// convert the d3 color scale to a texture
var colors = this.scales.image.model.color_range;
var colors = colorRange(this.scales.image.model);
var color_scale = d3.scaleLinear()
.range(colors)
.domain(_.range(colors.length).map((i) => i/(colors.length-1)));
Expand Down Expand Up @@ -370,23 +377,31 @@ class ImageGLView extends bqplot.Mark {
}

update_scene(animate) {
this.parent.update_gl();
request_webgl_render(this);
}

render_gl() {
render_bqplot_012_webgl() {
var fig = this.parent;
var renderer = fig.renderer;
var image = this.model.get("image");
var plotarea = get_bqplot_012_plotarea(fig);
this.render_webgl_mark(fig.renderer, this.camera, plotarea.width, plotarea.height);
}

render_bqplot_013_webgl() {
var fig = this.parent;
var plotarea = get_bqplot_013_plotarea(fig);
this.render_webgl_mark(fig.extras.webGLRenderer.renderer, this.camera, plotarea.width, plotarea.height);
}

render_webgl_mark(renderer, camera, plotarea_width, plotarea_height) {
var x_scale = this.scales.x ? this.scales.x : this.parent.scale_x;
var y_scale = this.scales.y ? this.scales.y : this.parent.scale_y;

// set the camera such that we work in pixel coordinates
this.camera.left = 0;
this.camera.right = fig.plotarea_width;
this.camera.bottom = 0;
this.camera.top = fig.plotarea_height;
this.camera.updateProjectionMatrix();
camera.left = 0;
camera.right = plotarea_width;
camera.bottom = 0;
camera.top = plotarea_height;
camera.updateProjectionMatrix();

var x = this.model.get('x');
var y = this.model.get('y');
Expand All @@ -397,7 +412,7 @@ class ImageGLView extends bqplot.Mark {

var pixel_width = x1_pixel - x0_pixel;
var pixel_height = y1_pixel - y0_pixel;
this.image_mesh.position.set(x0_pixel + pixel_width/2, fig.plotarea_height - (y0_pixel + pixel_height/2), 0);
this.image_mesh.position.set(x0_pixel + pixel_width/2, plotarea_height - (y0_pixel + pixel_height/2), 0);
this.image_mesh.scale.set(pixel_width, pixel_height, 1);

this.image_material.uniforms.range_x.value = x_scale.scale.range();
Expand All @@ -409,10 +424,18 @@ class ImageGLView extends bqplot.Mark {
this.image_material.uniforms.image_domain_x.value = [x0, x1];
this.image_material.uniforms.image_domain_y.value = [y0, y1];

renderer.render(this.scene, this.camera);
renderer.render(this.scene, camera);
var canvas = renderer.domElement;
}

render_gl() {
this.render_bqplot_012_webgl();
}

renderGL() {
this.render_bqplot_013_webgl();
}

relayout() {
this.update_scene();
}
Expand Down
Loading
Loading