As Jupyter is becoming so popular, I just want to integrate data processing and visualization together using Jupyter. But matplotlib and R ggplot2 are not flexible enough, so I want to use Javascript in Jupyter to draw cool graphs. I have noticed in the newest jupyter, I can write js code with %%javascript in the first line of a cell. But I haven't figured it out that how to exchange data between python and js. For example, in python, I process the data using some algorithms and want to visualize it using D3.js. How can I do that? Thanks for any reply.
Asked
Active
Viewed 571 times
2 Answers
0
Through the kernel object in the IPython Javascript package. A python statement can be executed from js as follows:
var kernel = IPython.notebook.kernel;
kernel.execute(command);

luminousmen
- 1,971
- 1
- 18
- 24
-
Thanks for your reply. if I do this, does it mean that I should assign my python code to a javascript string, and kernel.excute this string?@luminousmen – Sun Chuanneng Jan 22 '18 at 15:47
-
@SunChuanneng Not necessary. You can implement functions in python code and just call it in js. – luminousmen Jan 23 '18 at 07:41
0
I've been looking for similar solutions. This helped plus kernal.execute method. I wrote a class to wrap all of this up - interaction between python f-strings and converting into javascript variable
class setvariables {
constructor(IPython) {
//super(IPython);
this.__inprogress = {};
this.__kernel = IPython.notebook.kernel;
}
// results come back asynchronously. Check struct that records request is emply
// before calling requested callback after variables have been set
sync (callback) {
if (Object.keys(this.__inprogress).length === 0){
callback();
} else {
new Promise(resolve => setTimeout(resolve, 200)).then(() => {this.sync(callback);});
}
}
// can run anything - doing print("f{var}") and getting results in promise callbacks
execute(cmd) {
return new Promise((resolve, reject) => {
var callbacks = {
iopub: { output: (data) => resolve(data.content.text.trim()) }
};
this.__kernel.execute(cmd, callbacks);
});
}
// build an f-string to get variable from IPython environment
// format results execute callback function to assign to javascript variable
setjs(name, type, callback) {
var inprogress = this.__inprogress;
inprogress[name] = {"type": typeof(type)};
if (inprogress[name].type==="object" && type instanceof Array) {
inprogress[name].type="array";
} else if (inprogress[name].type==="object" && !(type instanceof Array)) {
inprogress[name].type="dict";
}
var cmd = 'print(f"{' + name + '}"';
// for dict and array replace double quotes to single quotes so JSON.parse works
if (["dict","array"].includes(inprogress[name].type)) {
cmd = cmd + '.replace(chr(39),chr(34))';
}
cmd = cmd + ')';
var p = this.execute(cmd);
p.then((result) => {
if (["dict","array"].includes(inprogress[name].type)) {
result = JSON.parse(result);
} else if (inprogress[name].type === "string") {
result = result.trim();
} else {
result = Number(result);
}
/// fetch complete so remove from dict of variables being fetched.
// Allows sync() to be reliable
delete inprogress[name];
callback(result);
}, (err) => {
console.warn(err, execute);
})
}
}
I intend to put this into a .js file and use require to load it into a %%javascript Jupyter cell. Sample usage below
var td = {};
var data = {};
var array = [];
var num = 0.0;
var str = "";
var py = new setvariables(IPython);
py.setjs("td", td, (result) => { td = result; } );
py.setjs("data", data, (result) => { data = result; } );
py.setjs("array", array, (result) => { array = result; } );
py.setjs("num", num, (result) => { num = result; } );
py.setjs("str", str, (result) => { str = result; } );
// everything is async - all code that depends on values from python needs to be called
// from this block
py.sync(() => {
console.log(td,"done");
console.log(data,"done");
console.log(array,"done");
console.log(num + 1,"done");
str = str + " Rob";
console.log(str,'done');
})

Rob Raymond
- 29,118
- 3
- 14
- 30