%rerun notebook cell

1,121 views
Skip to first unread message

TJ Lane

unread,
Feb 1, 2017, 10:02:03 PM2/1/17
to Project Jupyter
Hi Jupyter Community,

I am interested in setting up some very simple, low-performance "live" plots using matplotlib. Think line plot updating at ~1 Hz. Simplicity and keeping the "static" matplotlib interface intact are priorities.

My current vision for this is to write a magic function, %rerun <time>. This would declare that the code in that cell should be re-run after a specified time, perhaps defaulting to 1 or 10 seconds. The notebook could block while the cell is being re-evaluated, but should not block while waiting. This would let me write something like:

>>> %rerun
>>> data = fetch_new_data() # gets data from external server
>>> plt.plot(data)
>>> plt.show()

and get a new plot every second or so.

I am wondering if someone can give me some advice on how best to implement this in the notebook framework... I am a long time user, but unfamiliar with the architecture "under the hood". If people can anticipate issues (or explain why this is a terrible idea) that would be most appreciated.

I am currently thinking of trying to catch the end of the cell execution, and at that time, spawning a thread. This thread would just sleep for the specified time, before waking up, calling for the (re)execution of the specified cell, and then dying. Calling the cell again would spawn a new thread that would re-start the cycle. At any point, by removing or commenting the %rerun line, the user could break the cycle.

That plan brings up a number of specific questions:
* how can I find out what cell code is being executed in?
* how can I programmatically execute code in a cell?
* are there issues with spawning threads from the nb kernel?

I have searched around a bit and not found much documentation or many examples that made sense to my uninitiated mind... so thanks much for any help.

Best,

TJ

Thomas Kluyver

unread,
Feb 2, 2017, 9:54:16 AM2/2/17
to Project Jupyter
On 2 February 2017 at 03:02, TJ Lane <thomas.jo...@gmail.com> wrote:
My current vision for this is to write a magic function, %rerun <time>. This would declare that the code in that cell should be re-run after a specified time, perhaps defaulting to 1 or 10 seconds. The notebook could block while the cell is being re-evaluated, but should not block while waiting.

A quick and dirty way to implement this would be for the %rerun magic to display some Javascript which will execute the cell again in the frontend after a given delay.

Anything cleverer that I can think may be troublesome, because the notebook frontend won't be expecting output and may not handle it correctly.

TJ Lane

unread,
Feb 2, 2017, 2:10:53 PM2/2/17
to Project Jupyter
Thanks for this basic suggestion. I've whipped something up that seems promising. Currently I have one big issue, though: how can I get the cell index for the js code that is executing?! This seems like it should be simple, but I have been struggling lol. I can get the index of the selected or focused cell, but that doesn't help much.

Here's a minimal example I'm working from:

%%javascript

var interval = 10;

// need replacement for THIS next line
// should return this cell's index
var idx  = 0;

var cell = IPython.notebook.get_cell(idx);
element.append(idx + ' ')

var time = new Date();
element.append(time.getSeconds());

setTimeout(function(){
    cell.execute();
}, interval * 1000);


any help much much appreciated. Once this works it seems straight forward to put it in a magic.

TJ

Thomas Kluyver

unread,
Feb 3, 2017, 6:39:16 AM2/3/17
to Project Jupyter
On 2 February 2017 at 19:10, TJ Lane <thomas.jo...@gmail.com> wrote:
Currently I have one big issue, though: how can I get the cell index for the js code that is executing?! This seems like it should be simple, but I have been struggling lol.

I played around to see if I could do this. The only way I could do it was to walk up the DOM, which is hackish - it almost certainly won't work with Jupyterlab, for instance.

%%javascript
var cell_elt = this.element[0].parentElement.parentElement;
var cell_obj = $(cell_elt).data('cell')
console.log(cell_obj);

Kyle Kelley

unread,
Feb 3, 2017, 5:01:21 PM2/3/17
to jup...@googlegroups.com
Hey TJ,

I'm looking forward to the update display mechanics that are coming to a later release - see https://github.com/ipython/ipython/pull/10048 

I created an animation below that updates a figure in place (full replacement) every tenth of a second. This could also be done on a thread pool, targeting just one display:




-- Kyle


--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+unsubscribe@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/e85c1e1d-37e0-46af-825d-cda214d1e930%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Kyle Kelley (@rgbkrklambdaops.com)

TJ Lane

unread,
Feb 6, 2017, 12:00:29 AM2/6/17
to Project Jupyter
@kyle very cool! We would be early users of that. In fact, I plan to watch your work for future adoption -- let me know if I can help test or develop.

In the meantime, I came up with this rather hacky attempt. Should work for us in the mean time. Posting a sketch here in case it's of use/interest to anyone:


from IPython.core.magic import register_line_magic
from IPython.display import display, Javascript

@register_line_magic
def rerun(line):
   
    if len(line) > 0:
        try:
            seconds = int(line)
        except:
            raise ValueError('Could not understand %d as a time in (integral) '
                             'seconds after which to rerun the cell')
    else:
        seconds = 10

    js = """
    var interval = %d;


    var cell_elt  = this.element[0].parentElement.parentElement;
    var cell      = $(cell_elt).data('cell');
    var idx       = IPython.notebook.find_cell_index(cell);
    var lock_name = "rerun_lock_" + idx

    if (sessionStorage.getItem(lock_name) === null) {
        sessionStorage.setItem(lock_name, "off");
        console.log('setting first lock for cell :: ' + idx + ' :: OFF');
    };

    element.append('cell will rerun in: ' + interval + ' seconds');

    if  ( sessionStorage.getItem(lock_name) === 'off' ) {

        console.log('rerunning cell :: ' + idx);
        sessionStorage.setItem(lock_name, "on");
        console.log('lock for cell :: ' + idx + ' :: ON');

        setTimeout(function(){
            cell.execute();
            console.log('ran cell ' + idx);
            sessionStorage.setItem(lock_name, "off");
            console.log('lock for cell :: ' + idx + ' :: OFF');
        }, interval * 1000);

    };
    """ % seconds

    js_obj = Javascript(js)
    display(js_obj)

    return line
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.

To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/e85c1e1d-37e0-46af-825d-cda214d1e930%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Samuel Rizzo

unread,
Jun 28, 2019, 12:01:57 PM6/28/19
to Project Jupyter
In case anyone is still interested, I came up with https://github.com/srizzo/jupyter-live
Reply all
Reply to author
Forward
0 new messages