3

Within an ipython notebook, using Jupyter I try to do a calculation, thats running for an extended period of time in a while loop. I use pyplot to show the current status of my calculation and I would like to be able to communicate with the calculation and the plot via ipywidgets. For example this could be a stop button for the calculation, or a slider that adjusts the update rate of the plot.

Below I show a minimal example of a sin function, that is constantly plotted with different phase shifts. The start button starts the calculation, the stop button stops it and the slider should adjust the speed at which the whole thing is updated. The textbox shows the current phase shift.

import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import *
import IPython.display as display
import _thread
import time

%matplotlib nbagg

# set up widgets

buttons = widgets.ToggleButtons(
    options=['Stop', 'Start'],
    description='',
    disabled=False,
)

text = widgets.Text(
    value='0',
    placeholder='',
    description='Shift [rad]',
)

speed_slider = widgets.IntSlider(
    description = "Speed", 
    value = 100, 
    min = 10, 
    max = 500, 
    step = 10,
)

container = widgets.HBox(children = [buttons, speed_slider, text])

display.display(container)


# functions

def mySin(x, x0):
    return np.sin(x-x0)

def run_app(x, dx0):

    x0 = np.remainder(np.float(text.value), 2*np.pi)

    while buttons.value == buttons.options[1]:
        x0 = np.remainder(x0 + dx0, 2*np.pi)    
        line.set_ydata(mySin(x, x0))
        text.value = str(x0)
        time.sleep(speed_slider.value/1000)
        fig.canvas.draw()

# setup plot

N = 1000
x = np.linspace(0, 10*np.pi, N)
dx0 = 0.05*2*np.pi

fig, ax = plt.subplots(ncols = 1, nrows = 1, figsize = (8,3))
line    = ax.plot(x, mySin(x, np.float(text.value)))[0]

# act on button change

def buttons_on_changed(val):

    if buttons.value == buttons.options[1]:
        _thread.start_new_thread(run_app, (x, dx0))

buttons.observe(buttons_on_changed)

I try to run the function "run_app" in a new thread in order to make the interaction possible. I'm aware that _thread is deprecated, but I would like to know first, wether this is the right way to go. The example above works more or less, but the execution stops after a couple of seconds or when I do something else in the notebook (scrolling, clicking, ...). So my questions are the following:

  1. Is the Thread closing or just losing priority and why is it doing that?
  2. Is that a good approach at all, or can that be achieved in an easier way. Unfortunately, I haven't found anything browsing the web.

Thanks a lot, Frank

FMey
  • 31
  • 1

0 Answers0