0

In the following script, a plot window is created and values are correctly passed to plot.update. However, the plot is not updating. What am I doing wrong?

import sys
import time

import numpy
from numpy import pi

import rx
from rx.concurrency import QtScheduler

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui


class DemoData:

    def __init__(self, window, steps):

        def signal(t):
            omega = 5
            return numpy.sin(2*pi*omega*t) + numpy.random.random()

        self.stream = rx.Observable.range(
            0, steps
        ).map(
            signal
        ).buffer_with_count(
            window, 1
        )


class UpdatingPlot:

    def __init__(self):
        self.plot = pg.plot()
        self.curve = self.plot.plot()

    def update(self, values):
        self.curve.setData(values)


def main():

    app = QtGui.QApplication([])
    scheduler = QtScheduler(QtCore)

    window, steps = 50, 100
    data = DemoData(window, steps)
    plot = UpdatingPlot()

    data.stream.subscribe_on(scheduler=scheduler).subscribe(plot.update)

    sys.exit(app.exec_())


if __name__ == '__main__':

    main()
lafras
  • 8,712
  • 4
  • 29
  • 28

1 Answers1

1

This doesn't fix your issue, but it might fix your need. You can use the package joystick, install it using pip install joystick. It is designed to provide a real-time and interactive plotting framework.

Here is an example using it. It creates a graph-frame that 'listens' and displays your sine function as a function of time; a new data point is added every 0.2 sec.

import joystick as jk
import numpy as np
import time

class DemoData(jk.Joystick):
    # initialize the infinite loop and callit decorators so they can auto-
    # register methods they decorate
    _infinite_loop = jk.deco_infinite_loop()
    _callit = jk.deco_callit()

    @_callit('before', 'init')
    def _init_data(self, *args, **kwargs):
        # Function automatically called at initialization, thanks to the
        # decorator
        self.tdata = np.array([])  # time x-axis
        self.ydata = np.array([])  # data y-axis
        self.omega = 5

    @_callit('after', 'init')
    def _build_frames(self, *args, **kwargs):
        # Function automatically called at initialization, thanks to the
        # decorator.
        # Creates a graph frame
        self.mygraph = self.add_frame(
                   jk.Graph(name="DemoData", size=(500, 500), pos=(50, 50),
                            fmt="go-", xnpts=50, freq_up=7, bgcol="w",
                            xylim=(None,None,-1.1,2.1), xlabel='t', ylabel='sine'))

    @_callit('before', 'start')
    def _set_t0(self):
        # initialize t0 at start-up
        self._t0 = time.time()

    @_infinite_loop(wait_time=0.2)
    def _get_data(self):
        # This method will automatically be called with simulation start
        # (t.start()), and looped every 0.2 in a separate thread as long as
        # the simulation runs (running == True)
        # It generates new data and pushes it to the frame.
        # concatenate data on the time x-axis
        timestamp = time.time() - self._t0
        self.tdata = jk.add_datapoint(self.tdata,
                                      timestamp,
                                      xnptsmax=self.mygraph.xnptsmax)
        new_y_data = np.sin(2*np.pi*self.omega*timestamp) + np.random.random()
        self.ydata = jk.add_datapoint(self.ydata,
                                      new_y_data,
                                      xnptsmax=self.mygraph.xnptsmax)
        # push new data to the graph
        self.mygraph.set_xydata(np.round(self.tdata, 1), self.ydata)

d = DemoData()
d.start()
...
d.stop()
Guillaume S
  • 190
  • 2
  • 4