Skip to content

Commit cd0cccc

Browse files
author
Michael Recachinas
committed
mod: Update JS to start saving PNGs on export
1 parent 9072ca9 commit cd0cccc

File tree

3 files changed

+78
-24
lines changed

3 files changed

+78
-24
lines changed

example/JupyterSigplot.ipynb

+12-12
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
{
6565
"data": {
6666
"application/vnd.jupyter.widget-view+json": {
67-
"model_id": "3103064b836d4389bf9e78a1d9e4a2de",
67+
"model_id": "d55da0472865481e9ba2b8bd60751362",
6868
"version_major": 2,
6969
"version_minor": 0
7070
},
@@ -105,7 +105,7 @@
105105
{
106106
"data": {
107107
"application/vnd.jupyter.widget-view+json": {
108-
"model_id": "81ccf929f8ec49788f6d3f1f8f8bd306",
108+
"model_id": "286a5a00e11144f198be649b2953fd8e",
109109
"version_major": 2,
110110
"version_minor": 0
111111
},
@@ -120,8 +120,8 @@
120120
"name": "stdout",
121121
"output_type": "stream",
122122
"text": [
123-
"CPU times: user 574 ms, sys: 248 ms, total: 822 ms\n",
124-
"Wall time: 1.18 s\n"
123+
"CPU times: user 600 ms, sys: 271 ms, total: 871 ms\n",
124+
"Wall time: 1.23 s\n"
125125
]
126126
}
127127
],
@@ -145,7 +145,7 @@
145145
{
146146
"data": {
147147
"application/vnd.jupyter.widget-view+json": {
148-
"model_id": "3d24cd35cd494c08a508f730583216ab",
148+
"model_id": "08274f537c414f96851a922a755d2f15",
149149
"version_major": 2,
150150
"version_minor": 0
151151
},
@@ -174,7 +174,7 @@
174174
{
175175
"data": {
176176
"application/vnd.jupyter.widget-view+json": {
177-
"model_id": "e86f23bf590c443e8a01b32b60f81b63",
177+
"model_id": "b04048a5ab5540bb845de7ef0130a184",
178178
"version_major": 2,
179179
"version_minor": 0
180180
},
@@ -202,7 +202,7 @@
202202
{
203203
"data": {
204204
"application/vnd.jupyter.widget-view+json": {
205-
"model_id": "ec590395321041d38b868f7dd5dd2866",
205+
"model_id": "2ecd0044a5a24820888e185ad87f3883",
206206
"version_major": 2,
207207
"version_minor": 0
208208
},
@@ -232,7 +232,7 @@
232232
{
233233
"data": {
234234
"application/vnd.jupyter.widget-view+json": {
235-
"model_id": "787d8d74345648e99d71ff498aa2d3ba",
235+
"model_id": "9f90a5c33eae481f8095f199409dbf43",
236236
"version_major": 2,
237237
"version_minor": 0
238238
},
@@ -260,7 +260,7 @@
260260
{
261261
"data": {
262262
"application/vnd.jupyter.widget-view+json": {
263-
"model_id": "1826ad9644cb4a139c7fbf5b3653ed10",
263+
"model_id": "e8fb5d9eb302454e8c77494fb001bd67",
264264
"version_major": 2,
265265
"version_minor": 0
266266
},
@@ -289,7 +289,7 @@
289289
{
290290
"data": {
291291
"application/vnd.jupyter.widget-view+json": {
292-
"model_id": "73dfbd0c822849ec9c7ee25209717d64",
292+
"model_id": "f64bad11c9594a9a897e2284b57ee60d",
293293
"version_major": 2,
294294
"version_minor": 0
295295
},
@@ -314,7 +314,7 @@
314314
{
315315
"data": {
316316
"application/vnd.jupyter.widget-view+json": {
317-
"model_id": "cfeef435acf54f3cbff75136c70a1dee",
317+
"model_id": "026a739145774e159488fdb25ca4421c",
318318
"version_major": 2,
319319
"version_minor": 0
320320
},
@@ -342,7 +342,7 @@
342342
{
343343
"data": {
344344
"application/vnd.jupyter.widget-view+json": {
345-
"model_id": "a36369fc70534b7fb45c25b83811dd51",
345+
"model_id": "6f04f2fdbed146cb914ee17f692a9014",
346346
"version_major": 2,
347347
"version_minor": 0
348348
},

js/src/sigplot_ext.js

+32-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DOMWidgetModel, DOMWidgetView } from '@jupyter-widgets/base';
22
import { Plot } from 'sigplot';
33
import { version } from '../package';
4+
import { find_output_cell } from './utils';
45

56
export class SigPlotModel extends DOMWidgetModel {
67
defaults() {
@@ -67,7 +68,9 @@ export class SigPlotModel extends DOMWidgetModel {
6768
export class SigPlotView extends DOMWidgetView {
6869
render() {
6970
// Instantiate a new plot and attach to the element provided in `this.el`
70-
this.plot = new Plot(this.el, this.model.get('plot_options'));
71+
const plot_options = this.model.get('plot_options');
72+
this.plot = new Plot(this.el, plot_options);
73+
this.uuid = this.model.get('uuid');
7174

7275
// Wait for element to be added to the DOM
7376
const self = this;
@@ -91,6 +94,7 @@ export class SigPlotView extends DOMWidgetView {
9194
*/
9295
handle_command_args_change(prev_cmd_and_args, new_cmd_and_args) {
9396
const { command: new_command, arguments: new_args } = new_cmd_and_args;
97+
console.debug(`new_command=${new_command}`);
9498

9599
// Check that the commands and arguments are different
96100
if (prev_cmd_and_args === new_cmd_and_args) {
@@ -106,17 +110,33 @@ export class SigPlotView extends DOMWidgetView {
106110
// Call `new_command` providing `new_args`
107111
this.plot[new_command].apply(this.plot, new_args);
108112

109-
// Save a screenshot of the current plot
110-
const image_data = this.plot._Mx.active_canvas.toDataURL('image/png');
111-
const img = document.createElement('img');
112-
img.src = image_data;
113-
114-
// Replace existing image with new image
115-
const childImg = this.el.querySelector('img');
116-
if (childImg) {
117-
this.el.removeChild(childImg);
118-
}
119-
this.el.appendChild(img);
113+
const self = this;
114+
window.setTimeout(function () {
115+
// Save a screenshot of the current plot
116+
const image_data = self.plot._Mx.active_canvas.toDataURL(
117+
'image/png'
118+
);
119+
if (image_data === 'data:,') {
120+
console.debug('Empty `image_data`. Skipping...');
121+
return;
122+
}
123+
124+
// Find the current cell's output area
125+
if (window.IPython && !self.cell_info) {
126+
console.debug('IPython in namespace, finding output cell...');
127+
self.cell_info = find_output_cell(
128+
`<div id="${self.uuid}"></div>`
129+
);
130+
}
131+
132+
// Save the screenshot to the output cell
133+
if (self.cell_info) {
134+
console.debug(self.cell_info);
135+
self.cell_info[1][
136+
'text/html'
137+
] = `<img alt="SigPlot plot" src="${image_data}" width="100%">`;
138+
}
139+
}, 10);
120140
}
121141

122142
/**

js/src/utils.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*global IPython*/
2+
3+
/**
4+
* Return the cell and output element which can be found *uniquely* in the notebook.
5+
*
6+
* Note: This is a bit hacky, but it is done because the "notebook_saving.Notebook"
7+
* IPython event is triggered only after the cells have been serialised, which for
8+
* our purposes (turning an active figure into a static one), is too late.
9+
*
10+
* Taken from matplotlib's mpl.js
11+
*
12+
* @param {string} html_output
13+
* @returns {(*|number)[]}
14+
*/
15+
export function find_output_cell(html_output) {
16+
const cells = IPython.notebook.get_cells();
17+
for (let i = 0; i < cells.length; i++) {
18+
const cell = cells[i];
19+
if (cell.cell_type === 'code') {
20+
for (let j = 0; j < cell.output_area.outputs.length; j++) {
21+
let data = cell.output_area.outputs[j];
22+
if (data.data) {
23+
// IPython >= 3 moved mimebundle to data attribute of output
24+
data = data.data;
25+
}
26+
console.log(`cell_index=${i}`);
27+
console.log(data);
28+
if (data['text/html'] === html_output) {
29+
return [cell, data, j];
30+
}
31+
}
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)