Interactive timer in Jupyter notebook
I have a function that writes data and takes a while. While the data is being recorded, I would like to have a button that, when clicked, displays how much time has passed since the start of data collection.
Can this be done in Jupyter?
I am having problems because data collection is blocking the activation of the widget, and if I try to run the widget in the background, it will not receive an event on_click
until the data collection is complete. On the other hand, if I send the data collection to the background, then the data is lost after the background job completes.
Background job
from IPython.lib.backgroundjobs import BackgroundJobManager
from IPython.core.magic import register_line_magic
from IPython import get_ipython
jobs = BackgroundJobManager()
@register_line_magic
def background_job(line):
ip = get_ipython()
jobs.new(line, ip.user_global_ns)
Timer button
import ipywidgets as widgets
import time
def button_timer():
t0 = 0
button = widgets.Button(description="Measure time")
def action(b):
time_elapsed = time.perf_counter() - t0
display("Time elapsed: {}".format(time_elapsed))
button.on_click(action)
display(button)
t0 = time.perf_counter()
Data collection
import numpy as np
import pandas as pd
import time
def acquire(a=None):
time.sleep(10)
print("Done")
if a is None:
return np.linspace(0, 10, 10)
else:
a = np.linspace(0, 10, 10)
## Implementation 1
# This fails because the `on_click` event for the button only runs after the data has been acquired.
button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
data['y'] = acquire()
## Implementation 2
# As before, the `on_click` event isn't activated until after the data has been acquired.
%background_job button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
data['y'] = acquire()
## Implementation 3
# This one fails as the data isn't actually updated
button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
# I can't use the equal sign as that isn't supported by the background job.
# %background_job data['y'] = acquire()
# If I pass in the data I want, the DataFrame isn't updated (even after I wait for the background job to finish)
%background_job acquire(data['y'])
display(data)
If all else fails, I suppose one option would only have a Javascript timer that works entirely in the browser.
However, I'm wondering if there is a way to do this in Python (and, if possible, have it in such a way that the (last) measured time is programmatically available in the rest of the notebook).
source to share
No one has answered this question yet
Check out similar questions: