pyCBD.realtime.plotting module

This module contains all classes and structures needed for live plotting of data via polling an object. While specifically made for the CBD simulator, it is independent of any internal workings.

class pyCBD.realtime.plotting.Backend[source]

Bases: object

In which framework the plots need to be made.

Note

Some attributes won’t be available if the corresponding framework is not installed.

MPL = 1

Use Matplotlib.

MATPLOTLIB = 1

Use Matplotlib.

BKH = 2
BOKEH = 2

Use Bokeh.

Important

For BOKEH, a server must be started with:

bokeh serve <experiment file>

Warning

Because of how Bokeh works, it is currently impossible to capture premature close events on a system. The plots will always remain active once started.

SNS

Use Seaborn.

SEABORN

Use Seaborn.

static exists(value)[source]

Checks that a given backend exists.

static compare(name, value)[source]

Compares the value against a backend name.

Parameters
  • name (str) – The name of the backend to check for.

  • value (int) – The value to compare.

static get(name)[source]

Gets the backend with a specific name if it exists and if it’s installed.

Parameters

name (str) – The name of the backend to get.

class pyCBD.realtime.plotting.PlotHandler(object, figure, kind, backend=1, interval=10, frames=None, static=False)[source]

Bases: object

Handles Real-Time plotting, independent of a plotting framework.

Every interval time, data will be polled from the object, w.r.t. the given plotting backend. The handler will use the knowledge of a backend to determine how the given figure must be updated.

This class can be used in any simulation context, where plotting data can be polled from an object or a resource.

Note

While technically framework-independent, matplotlib has the least external overhead in your code.

Tip

When using multiple plots/plotting instances, you should make use of the PlotManager.

Warning

Bokeh is still in active development. Not all features will work as required.

Raises

AssertionError – if the backend cannot be located.

Parameters
  • object (Any) – The object from which data needs to be polled. By default, the data_xy attribute will be used on the object, which should result in a 2xN array in the form of [[x1, x2, x3...], [y1, y2, y3...]]. Change this behaviour with the set_data_getter() function.

  • figure –

    The figure object required for plotting. This has been made externally to allow for full manipulation of the plotting framework itself. The following explains the axxepted data types:

    • matplotlib: Tuple (pair) of (Figure, Axes)

    • bokeh: Figure

    • seaborn: Tuple (pair) of (Figure, Axes)

  • kind (PlotKind) – What needs to be plotted. See PlotKind for more info.

  • backend (Backend) – The backend to use for plotting. Defaults to Backend.MPL (= matplotlib).

  • interval (int) – Amount of milliseconds between plot refreshes.

  • frames (int) – The amount of frames for the animation. Only used if the animation needs to be saved.

  • static (bool) – When True, no animation will be created.

signal(name, *args)[source]

Raise a signal with a specific name and arguments.

The accepted signals are:

  • preupdate(data): Raised whenever the plot is about to update. It takes the new plot data that has been polled.

  • update(data): Raised whenever the plot updates. It takes the new plot data that has been polled.

  • closed: Raised whenever the plot closes. No additional arguments are associated with this event.

Note

Normally, users do not need to call this function.

Parameters
  • name (str) – The name of the signal to raise.

  • *args – Additional arguments to pass to the connected events.

connect(name, function)[source]

Connect an event with an additional function. Useful for e.g. updating the plot axes w.r.t. the data.

The functions will be called in the order they were connected to the events, with the associated arguments. The accepted signals are:

  • preupdate(data): Raised whenever the plot is about to update. It takes the new plot data that has been polled.

  • update(data): Raised whenever the plot updates. It takes the new plot data that has been polled.

  • closed: Raised whenever the plot closes. No additional arguments are associated with this event.

Parameters
  • name (str) – The name of the signal to raise.

  • function – A function that will be called with the optional arguments whenever the event is raised.

set_data_getter(function)[source]

Sets the data getter function call. By default, the data_xy attribute is polled, but this function provides the flexibility to alter this behaviour.

Parameters

function – The function to obtain the data. Takes the object as an input and should return a 2xN array in the form of [[x1, x2, x3...], [y1, y2, y3...]].

get_data()[source]

Actually gets the data from the object.

get_animation()[source]

Returns the animation object, if MatPlotLib is used as a backend.

close_event()[source]

Closes the plot/figure associated with this handler.

is_opened()[source]

Checks if the plots are still open.

update()[source]

Updates the plot information.

stop()[source]

Requests the process to finish polling.

terminate()[source]

Terminate the animation and close the plot.

set_kind_args(*args, **kwargs)[source]

Sets the (keyword) arguments used for the plot.

hide()[source]

Hides the plot in the view.

See also

show()[source]

Shows the plot in the view.

See also

toggle()[source]

Toggles between hiding and showing the plot in the view.

See also

pyCBD.realtime.plotting.follow(data, size=None, lower_bound=- inf, upper_bound=inf, lower_lim=0.0, upper_lim=0.0, perc_keep=0.5)[source]

Compute the new limits for the given dataset if the last data point must be followed. This is a convenience function for updating the plotting axes’ limits. Whenever not enough data is available, the axis won’t scale down.

Parameters
  • data (list) – The data that must be plotted on the axes. Can be a shortened version of only the final n values (n > 0).

  • size (float) – The total size of the axis to show, even if the data did not get there. When None, the size is taken from the bounds or limits. Defaults to None.

  • lower_bound (float) – The lower bound of the axis, i.e. the minimal value to show, even if the data lies outside of this interval. Defaults to -float('inf') (-infinity = no limit).

  • upper_bound (float) – The upper bound of the axis, i.e. the maximal value to show, even if the data lies outside of this interval. Defaults to float('inf') (infinity = no limit).

  • lower_lim (float) – Lowest value to show, even if this value is not reached. While lower_bound bounds this point, so no smaller values can be shown, lower_limit makes it so this valus is always shown, but smaller values may still rescale beyond this point. Will be ignored when size is set. Defaults to 0.0.

  • upper_lim (float) – Highest value to show, even if this value is not reached. While upper_bound bounds this point, so no higher values can be shown, upper_limit makes it so this valus is always shown, but larger values may still rescale beyond this point. Will be ignored when size is set. Defaults to 0.0.

  • perc_keep (float) – The percentage at which the final data point must be shown. When 0.0, this point is the lowest value shown. When 1.0, this point is the highest value shown. Use this value to change how “centered” the last datapoint will be. When the axis grows in a positive direction, a value of 0.0 will never show the data. When growing negatively, the opposite is true: the data will not be shown for a value of 1.0. Defaults to 0.5 (= the middle).

Warning

  • The lower bound must be strictly smaller than the upper bound.

  • The size is None and the bounds are infinity and the limits are equal.

  • The size cannot be larger than the distance between the bounds.

  • The lower limit must be smaller than (or equal to) the upper limit.

Examples

  • Follow a sine wave in the positive-x direction, always keeping a width of 10, in matplotlib.

manager = PlotManager()
manager.register("sin", cbd.find("plot")[0], (fig, ax), LinePlot())
manager.connect('sin', 'update', lambda d, a=ax: a.set_xlim(follow(d[0], 10.0, lower_bound=0.0)))
  • Follow a sine wave in the negative-x direction, always keeping a width of 10, in matplotlib.

manager = PlotManager()
manager.register("sin", cbd.find("plot")[0], (fig, ax), LinePlot())
manager.connect('sin', 'update', lambda d, a=ax: a.set_xlim(follow(d[0], 10.0, upper_bound=0.0)))
  • Follow a positive sine-wave, but keep a 10% margin from the right edge of the plot, in matplotlib.

manager = PlotManager()
manager.register("sin", cbd.find("plot")[0], (fig, ax), LinePlot())
manager.connect('sin', 'update', lambda d, a=ax: a.set_xlim(follow(d[0], 10.0, 0.0, perc_keep=0.9)))
class pyCBD.realtime.plotting.PlotKind(*args, **kwargs)[source]

Bases: object

The kind of plot that needs to be rendered. This class is an abstract superclass.

Not all backends provide the same functionality for plotting the same shape. This class provides a wrapper around all those functionalities to allow for users that they only need to change the figure information.

Parameters
  • *args –

    The arguments to add to the ‘shape’, excluding the data points.

    Note

    The seaborn backend does not require any normal args.

  • **kwargs – The keyword arguments to add to the ‘shape’.

See also

is_backend(*backends)[source]

Checks the backend for the plot.

create(figure)[source]

Called when the figure is first created in the manager.

Returns

The ‘shape’ information that is created on the plot.

update(element, *data)[source]

Called when the figure is updated in the manager.

Parameters
  • element – The shape that was returned from the PlotKind.create() method.

  • *data – The data with which to update the plot.

class pyCBD.realtime.plotting.LinePlot(*args, **kwargs)[source]

Bases: pyCBD.realtime.plotting.PlotKind

Draws a line between all given coordinates.

Backend Information:
  • matplotlib: matplotlib.axes.Axes.plot()

  • bokeh: bokeh.plotting.Figure.line()

  • seaborn: seaborn.lineplot()

create(figure)[source]

Called when the figure is first created in the manager.

Returns

The ‘shape’ information that is created on the plot.

update(element, *data)[source]

Called when the figure is updated in the manager.

Parameters
  • element – The shape that was returned from the PlotKind.create() method.

  • *data – The data with which to update the plot.

class pyCBD.realtime.plotting.StepPlot(*args, **kwargs)[source]

Bases: pyCBD.realtime.plotting.PlotKind

Draws a stepped line between all given coordinates. See the corresponding backend information to change the step “levels”.

Backend Information:
  • matplotlib: matplotlib.axes.Axes.step()

  • bokeh: bokeh.plotting.Figure.step()

  • seaborn: seaborn.lineplot() with drawstyle='steps-pre'

create(figure)[source]

Called when the figure is first created in the manager.

Returns

The ‘shape’ information that is created on the plot.

update(element, *data)[source]

Called when the figure is updated in the manager.

Parameters
  • element – The shape that was returned from the PlotKind.create() method.

  • *data – The data with which to update the plot.

class pyCBD.realtime.plotting.ScatterPlot(*args, **kwargs)[source]

Bases: pyCBD.realtime.plotting.PlotKind

Draws all given coordinates as points in a 2D space. See the corresponding backend information to change the shape of the indicators.

Backend Information:
  • matplotlib: matplotlib.axes.Axes.scatter()

  • bokeh: bokeh.plotting.Figure.scatter()

  • seaborn: seaborn.scatterplot()

create(figure)[source]

Called when the figure is first created in the manager.

Returns

The ‘shape’ information that is created on the plot.

update(element, *data)[source]

Called when the figure is updated in the manager.

Parameters
  • element – The shape that was returned from the PlotKind.create() method.

  • *data – The data with which to update the plot.

class pyCBD.realtime.plotting.Arrow(size, position, *args, **kwargs)[source]

Bases: pyCBD.realtime.plotting.PlotKind

Draws a “direction” arrow at a position, indicative of an angle. This PlotKind assumes that the y-component indicates the angle.

Backend Information:
  • matplotlib: matplotlib.axes.Axes.scatter()

  • bokeh: Not available.

  • seaborn: Not available.

create(figure)[source]

Called when the figure is first created in the manager.

Returns

The ‘shape’ information that is created on the plot.

update(element, *data)[source]

Called when the figure is updated in the manager.

Parameters
  • element – The shape that was returned from the PlotKind.create() method.

  • *data – The data with which to update the plot.

class pyCBD.realtime.plotting.PlotManager(backend=1)[source]

Bases: object

Manages multiple PlotHandler instances. Use this class as a centralized unit to manage one or more plots in the system.

Parameters

backend (Backend) – The backend to use.

Raises

AssertionError – if the backend cannot be located.

See also

is_opened()[source]

Checks if there is at least a single plot left open.

all_opened()[source]

Checks if all plots are still open.

register(name, object, figure, kind, **kwargs)[source]

Register a single PlotHandler to plot information.

Parameters
  • name (str) – The name for this handler. Will be used to optionally access it afterwards.

  • object (Any) – The object from which data needs to be polled. By default, the data_xy attribute will be used on the object, which should result in a 2xN array in the form of ([x1, x2, x3...], [y1, y2, y3...]).

  • figure – The figure object required for plotting. This has been made externally to allow for full manipulation of the plotting framework itself.

  • kind (PlotKind) – What needs to be plotted. See PlotKind for more info.

  • **kwargs – Additional arguments to pass to the PlotHandler constructor.

See also

PlotHandler

unregister(name)[source]

Removes a single PlotHandler from the manager.

Parameters

name (str) – The identifying name for the handler.

get(name)[source]

Obtains a single PlotHandler, given its name.

Parameters

name (str) – The identifying name for the handler to obtain.

connect(handler_name, event_name, function)[source]

Connect an event to a specific handler.

Parameters
  • handler_name (str) – The identifying name for the handler.

  • event_name (str) – The name for the event.

  • function – A function to execute whenever the event is raised.

terminate()[source]

Forcibly terminate the manager and all its handlers.

stop()[source]

Stop polling for all updates.

set_xlim(figure, values)[source]

Shorthand method for setting the x limits of the figure.

Warning

Bokeh requires this method to be called in a “clean” tick. Call bokeh_set_xlim() instead.

Parameters
  • figure – The figure to alter.

  • values (tuple) – The new limits for the x-axis.

set_ylim(figure, values)[source]

Shorthand method for setting the y limits of the figure.

Warning

Bokeh requires this method to be called in a “clean” tick. Call bokeh_set_ylim() instead.

Parameters
  • figure – The figure to alter.

  • values (tuple) – The new limits for the y-axis.

bokeh_set_xlim(figure, doc, values)[source]

Helper function to set the x limits in Bokeh, as it should be called in a “safe” tick.

Parameters
  • figure – The figure to set the x limits for.

  • doc – The Bokeh document to which the figure belongs.

  • values – The new x limits.

bokeh_set_ylim(figure, doc, values)[source]

Helper function to set the y limits in Bokeh, as it should be called in a “safe” tick.

Parameters
  • figure – The figure to set the y limits for.

  • doc – The Bokeh document to which the figure belongs.

  • values – The new y limits.

pyCBD.realtime.plotting.plot(object, figure, kind, backend=1, margin=(0.02, 0.02))[source]

Plot data on a figure after the simulation has finished. This will automatically plot the full graph, so all axis scaling needs to be done afterwards.

Parameters
  • object (Any) – The object from which data needs to be polled. By default, the data_xy attribute will be used on the object, which should result in a 2xN array in the form of ([x1, x2, x3...], [y1, y2, y3...]).

  • figure – The figure object required for plotting. This has been made externally to allow for full manipulation of the plotting framework itself.

  • kind (PlotKind) – What needs to be plotted. See PlotKind for more info.

  • backend (Backend) – The backend to use.

  • margin (tuple) – A margin for the limits of the axes.

See also

PlotHandler