8

So, I've been playing around with the IPython notebook for a couple of days, and I love it! But, now I need to do something slightly fancy:

I have a markdown cell; in it, there is an HTML input and button, and some JavaScript attached to the button that will take the contents of the input, and inject it into the python kernel. Here's the cell:

<h3>Use JS to pass DOM info to Python kernel: </h3>
<input id='testinput' value='FragmentId'></input>
<button id='testComms' onclick='JS2PY()'>:D</button>

<script type="text/javascript">    
    function JS2PY(){
        var input = document.getElementById('testinput').value,
            kernel = IPython.notebook.kernel;

        kernel.execute('testVar = "' + input + '"');
    }
</script>

Works like a charm! Next up I have a python code cell; it does some ROOT stuff, and makes a plot based on whatever value got injected into the python kernel from the above cell. Here's the python cell:

def testfunc():
    from ROOT import TH1, TFile, TTree
    import rootnotes, numpy

    c2 = rootnotes.canvas("treeData", (600,400))

    testfile = TFile("fragment27422_000.root")
    testtree = testfile.Get("FragmentTree")

    buff = numpy.zeros(1, dtype=float)

    testtree.Branch(testVar, buff)

    testtree.Draw(testVar)
    return c2

testfunc()

Also works no problem if I manually go and run the cell - great! But what I really want, is this python cell to run automatically when I click that button in the markdown cell above, after promoting the testVar variable. Apologies and thanks in advance - this is only day two of python for me, so it's probably something really simple.

2 Answers 2

10

Solution / workaround: instead of triggering other cells directly, we can call python functions defined in other cells and get a round trip between JavaScript and the python kernel with a callback thereafter, all via IPython.notebook.kernel.execute; something like this code cell:

%%HTML

<div id='testwrap'>
<input id='varname'></input>
<img id='imgtarget'></img>
<button id='fetchplot' onclick='exec_code()'>Plot</button>
</div>

<script type="text/Javascript">
    function handle_output(out_type, out){
        document.getElementById('imgtarget').src = 'data:image/png;base64,' + out.data['image/png'];
    }

    function exec_code(){
        var kernel = IPython.notebook.kernel;
        var callbacks = {'output' : handle_output};
        kernel.execute('testVar = "' + document.getElementById('varname').value + '"');
        kernel.execute('testfunc(testVar)', callbacks, {silent:false});
    }
</script>

The first kernel.execute kicks some data up to the kernel from the DOM, and the second one uses a callback to do stuff in JS with whatever the python function testfunc (defined in some other cell) returns.

Big ups to http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/ for the bones of this solution!

Sign up to request clarification or add additional context in comments.

Comments

0

interesting first project with the notebooks (well the post is a bit old by now). Nowadays, one can use IPython.notebook.execute_cell(..) like so:

%%HTML

<h3>Select an Experiment</h3>
<input id='input' value='my input var'></input>
<button id='testComms' onclick='JS2PY()'>:D</button>

<script type="text/javascript">    
    function JS2PY() {
        const { value } = document.getElementById('input');
        const pycode = `testVar = '${value}'`;
        const { notebook } = IPython;
        const { kernel } = notebook;
        kernel.execute(pycode);
        // run cell using `testVar`
        notebook.select_next();
        notebook.execute_cell();
    }
</script>

In the example above, the next notebook cell should contain the code you'd like to execute.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.