How to output SVG to Jupyter notebook using jsdom, D3 and IJavascript

I'm not very good at front-end development, but I've been playing around a lot with Javascript and D3 lately. Having been using scientific analysis in Python with Jupyter Notebooks, I figured it should be possible to use a similar workflow to develop scientific visualizations with D3 using JS code in a Jupiter notebook with JS core. I looked at the n-riesco IJavascript project and it seems promising, but when trying to import D3 the laptop throws an error:

// npm install d3
var d3 = require('d3');

      

throws

ReferenceError: document is not defined

      

I assume this is because there is no DOM in the Jupyter environment ( as Mike Bostock says ). In fact, if I import jsdom

, D3 imports successfully as well. Awesome! However, now I can't select anything because ... well, I guess because in the Jupyter environment, there is nothing to select.

What I would like to do is either something like:

$$svg$$ = "<svg><rect width=1000 height=1000/></svg>";
var svg = d3.select("svg")
// Beautiful D3 code

      

Or (less cool, but also favorable), get a DOM reference on some local server, after which I can manipulate by executing the code in the notebook.


Update

With the introduction of Observable, you no longer need to use JavaScript in Jupyter notebooks. The Observable is a wonderful JavaScript notebook environment that can pretty much do everything. For example, what I wanted to do when I asked this question can be done in the same way as:

enter image description here

+4


source to share


2 answers


Let me first give a working example (tested for ijavascript@5.0.19

, jsdom@9.12.0

and d3@4.8.0

) and then some clarification:

var jsdom = require("jsdom");
global.document = jsdom.jsdom();

var d3 = require("d3");

var svg = d3.select(document.body).append("svg");

svg.append("rect")
    .attr("width", 80)
    .attr("height", 80)
    .style("fill", "orange");

$$.svg(svg.node().outerHTML);

      

screenshot from 2017-04-20 09-32-53

This solution:

  • uses the DOM provided by jsdom .

  • uses d3 to create <svg>

    node and add<rect>

  • uses outerHTML

    to get the string representation of the <svg>

    node created in the previous steps

  • and finally instructs IJavascript to return that string to Jupyter notebook as an SVG result.

    / li>


In theory, IJavascript can inject javascript code into Jupyter notebook (to manipulate its DOM), but this code may not work (depending on the security policies of the Jupyter interface).


Since your interest is scientific analysis, you may be interested in the recently published module: ijavascript-plotly .


I know this answer goes over many concepts. Please use the comments below if you need me to update the answer and explain something else.

+5


source


A similar approach for D3 rendering in Jupyter:



var d3 = require("d3");
var jsdom = require("jsdom");

var dom = new jsdom.JSDOM("<svg></svg>",{QuerySelector:true});

var svg = dom.window.document.querySelector("svg");

d3.select(svg)
    .append("rect")
    .attr("width", 80)
    .attr("height", 80)
    .style("fill", "orange");

$$.html(dom.serialize());

      

0


source







All Articles