Streaming events to a plot#
This notebook will illustrate how a plot can be continuously updated with new incoming data, without hogging the event loop, meaning that interacting with the plot (zooming, panning, …) is possible while the data is streaming in.
Working in other notebook cells is also possible while the plot is updating.
[1]:
import scipp as sc
import plopp as pp
import ipywidgets as ipw
%matplotlib widget
Create a data generator#
We create an object which generates new data points when its update
method is called.
[2]:
import numpy as np
class DataGen:
"""A data generator which makes new data when asked"""
def __init__(self):
# Make an empty container with 300x300 bins
nx, ny = 300, 300
xmin, xmax = -10.0, 10.0
ymin, ymax = -10.0, 10.0
self.data = sc.DataArray(data=sc.zeros(sizes={'y': ny, 'x': nx}),
coords={'x': sc.linspace('x', xmin, xmax, nx+1, unit='m'),
'y': sc.linspace('y', ymin, ymax, ny+1, unit='m')})
def __call__(self, iteration: int=0):
# Generate new data when called
npoints = 100
x = sc.array(dims=['event'], values=np.random.normal(scale=2, size=npoints), unit='m')
y = sc.array(dims=['event'], values=np.random.normal(scale=2, size=npoints), unit='m')
new_events = sc.DataArray(
data=sc.ones(sizes=x.sizes, unit=""),
coords={'x': x, 'y': y})
# Histogram and add to container
self.data += new_events.hist({xy: self.data.coords[xy] for xy in "xy"})
return self.data
data = DataGen()
Connecting the data generator to a Play widget#
We now use ipywidgets
’s Play widget to continuously send updates at regular intervals.
[3]:
# Create a play widget that fires every 100 ms
play = ipw.Play(min=0, max=500, interval=100)
# Wrap the widget in a widget node
play_node = pp.widget_node(play)
# Connect the widget to the data generator.
# Note that `data` here is not a function, but our generator
# class that has a `__call__` method defined.
stream_node = pp.Node(data, iteration=play_node)
# Plot on a figure
fig = pp.imagefigure(stream_node, norm="log", cbar=True)
[5]:
# Display figure a play widget
ipw.VBox([fig, play])
[5]:
After pressing play, data starts collecting on the plot.
Zooming and panning is still possible while the image is updating
Working elsewhere in the notebook is also not blocked by the updating plot
[6]:
pp.show_graph(fig)
[6]: