コード例 #1
0
    def __init__(
        self,
        capacity: Optional[int],
        linked_curve: pg.PlotDataItem,
        shift_right_x_to_zero: bool = False,
        use_ringbuffer=None,  # Deprecated arg for backwards compatibility # pylint: disable=unused-argument
    ):
        self.capacity = capacity
        self.curve = linked_curve
        self.opts = self.curve.opts  # Use for read-only

        self._shift_right_x_to_zero = shift_right_x_to_zero
        self._use_ringbuffer = capacity is not None
        self._mutex = QtCore.QMutex()  # To allow proper multithreading

        self.x_axis_divisor = 1
        self.y_axis_divisor = 1

        if self._use_ringbuffer:
            self._buffer_x = RingBuffer(capacity=capacity)
            self._buffer_y = RingBuffer(capacity=capacity)
        else:
            self._buffer_x = np.array([])
            self._buffer_y = np.array([])

        self._snapshot_x = np.array([])
        self._snapshot_y = np.array([])
コード例 #2
0
    def test_sizes(self):
        r = RingBuffer(5, dtype=(int, 2))
        self.assertEqual(r.maxlen, 5)
        self.assertEqual(len(r), 0)
        self.assertEqual(r.shape, (0, 2))

        r.append([0, 0])
        self.assertEqual(r.maxlen, 5)
        self.assertEqual(len(r), 1)
        self.assertEqual(r.shape, (1, 2))
コード例 #3
0
    def test_degenerate(self):
        r = RingBuffer(0)
        np.testing.assert_equal(r, np.array([]))

        # this does not error with deque(maxlen=0), so should not error here
        try:
            r.append(0)
            r.appendleft(0)
            r.extend([0])
            r.extendleft([0])
        except IndexError:
            self.fail()
コード例 #4
0
    def test_dtype(self):
        r = RingBuffer(5)
        self.assertEqual(r.dtype, np.dtype(float))

        r.clear()
        self.assertEqual(r.dtype, np.dtype(float))

        r = RingBuffer(5, dtype=bool)
        self.assertEqual(r.dtype, np.dtype(bool))

        r.clear()
        self.assertEqual(r.dtype, np.dtype(bool))
コード例 #5
0
    def test_iter(self):
        r = RingBuffer(5)
        for i in range(3):
            r.append(i)
        for i, j in zip(r, range(3)):
            self.assertEqual(i, j)

        r.clear()
        for i in range(5):
            r.append(i)
        for i, j in zip(r, range(5)):
            self.assertEqual(i, j)
コード例 #6
0
    def test_getitem(self):
        r = RingBuffer(5)
        r.extend([1, 2, 3])
        r.extendleft([4, 5])
        expected = np.array([4, 5, 1, 2, 3])
        np.testing.assert_equal(r, expected)

        for i in range(r.maxlen):
            self.assertEqual(expected[i], r[i])

        ii = [0, 4, 3, 1, 2]
        np.testing.assert_equal(r[ii], expected[ii])
コード例 #7
0
    def test_2d(self):
        r = RingBuffer(5, dtype=(float, 2))

        r.append([1, 2])
        np.testing.assert_equal(r, np.array([[1, 2]]))
        self.assertEqual(len(r), 1)
        self.assertEqual(np.shape(r), (1, 2))

        r.append([3, 4])
        np.testing.assert_equal(r, np.array([[1, 2], [3, 4]]))
        self.assertEqual(len(r), 2)
        self.assertEqual(np.shape(r), (2, 2))

        r.appendleft([5, 6])
        np.testing.assert_equal(r, np.array([[5, 6], [1, 2], [3, 4]]))
        self.assertEqual(len(r), 3)
        self.assertEqual(np.shape(r), (3, 2))

        np.testing.assert_equal(r[0], [5, 6])
        np.testing.assert_equal(r[0, :], [5, 6])
        np.testing.assert_equal(r[:, 0], [5, 1, 3])
コード例 #8
0
    def test_errors(self):
        r = RingBuffer(5)

        r.extend([1, 2, 3, 4, 5])
        with self.assertRaisesRegex(TypeError, "integers"):
            r[2.0]
        with self.assertRaisesRegex(IndexError, "out of range"):
            r[5]
        with self.assertRaisesRegex(IndexError, "out of range"):
            r[np.array([-6, 5])]

        r.clear()
        with self.assertRaisesRegex(IndexError, "length 0"):
            r[2]
コード例 #9
0
    def test_extend(self):
        r = RingBuffer(5)

        r.extend([1, 2, 3])
        np.testing.assert_equal(r, np.array([1, 2, 3]))

        r.popleft()
        r.extend([4, 5, 6])
        np.testing.assert_equal(r, np.array([2, 3, 4, 5, 6]))

        r.extendleft([0, 1])
        np.testing.assert_equal(r, np.array([0, 1, 2, 3, 4]))

        r.extendleft([1, 2, 3, 4, 5, 6, 7])
        np.testing.assert_equal(r, np.array([1, 2, 3, 4, 5]))

        r.extend([1, 2, 3, 4, 5, 6, 7])
        np.testing.assert_equal(r, np.array([3, 4, 5, 6, 7]))
コード例 #10
0
    def test_appendleft(self):
        r = RingBuffer(5)

        r.appendleft(1)
        np.testing.assert_equal(r, np.array([1]))
        self.assertEqual(len(r), 1)

        r.appendleft(2)
        np.testing.assert_equal(r, np.array([2, 1]))
        self.assertEqual(len(r), 2)

        r.appendleft(3)
        r.appendleft(4)
        r.appendleft(5)
        np.testing.assert_equal(r, np.array([5, 4, 3, 2, 1]))
        self.assertEqual(len(r), 5)

        r.appendleft(6)
        np.testing.assert_equal(r, np.array([6, 5, 4, 3, 2]))
        self.assertEqual(len(r), 5)
コード例 #11
0
    def test_append(self):
        r = RingBuffer(5)

        r.append(1)
        np.testing.assert_equal(r, np.array([1]))
        self.assertEqual(len(r), 1)

        r.append(2)
        np.testing.assert_equal(r, np.array([1, 2]))
        self.assertEqual(len(r), 2)

        r.append(3)
        r.append(4)
        r.append(5)
        np.testing.assert_equal(r, np.array([1, 2, 3, 4, 5]))
        self.assertEqual(len(r), 5)

        r.append(6)
        np.testing.assert_equal(r, np.array([2, 3, 4, 5, 6]))
        self.assertEqual(len(r), 5)

        self.assertEqual(r[4], 6)
        self.assertEqual(r[-1], 6)
コード例 #12
0
    def test_pops(self):
        r = RingBuffer(3)
        r.append(1)
        r.appendleft(2)
        r.append(3)
        np.testing.assert_equal(r, np.array([2, 1, 3]))

        self.assertEqual(r.pop(), 3)
        np.testing.assert_equal(r, np.array([2, 1]))

        self.assertEqual(r.popleft(), 2)
        np.testing.assert_equal(r, np.array([1]))

        # test empty pops
        empty = RingBuffer(1)
        with self.assertRaisesRegex(IndexError, "empty"):
            empty.pop()
        with self.assertRaisesRegex(IndexError, "empty"):
            empty.popleft()
コード例 #13
0
    def test_no_overwrite(self):
        r = RingBuffer(3, allow_overwrite=False)
        r.append(1)
        r.append(2)
        r.appendleft(3)
        with self.assertRaisesRegex(IndexError, "overwrite"):
            r.appendleft(4)
        with self.assertRaisesRegex(IndexError, "overwrite"):
            r.extendleft([4])
        r.extendleft([])

        np.testing.assert_equal(r, np.array([3, 1, 2]))
        with self.assertRaisesRegex(IndexError, "overwrite"):
            r.append(4)
        with self.assertRaisesRegex(IndexError, "overwrite"):
            r.extend([4])
        r.extend([])

        # works fine if we pop the surplus
        r.pop()
        r.append(4)
        np.testing.assert_equal(r, np.array([3, 1, 4]))
コード例 #14
0
    def test_repr(self):
        r = RingBuffer(5, dtype=int)
        for i in range(5):
            r.append(i)

        self.assertEqual(repr(r), "<RingBuffer of array([0, 1, 2, 3, 4])>")
コード例 #15
0
        def __init__(self, block_size: int, N_blocks: int):
            """Reflects the actual readings, parsed into separate variables, of
            the lock-in amplifier. There should only be one instance of the
            State class.
            """

            # fmt: off
            self.block_size  = block_size
            self.N_blocks    = N_blocks
            self.rb_capacity = block_size * N_blocks
            self.blocks_received = 0

            # Arrays to hold the block data coming from the lock-in amplifier
            # Keep `time` as `dtype=np.float64`, because it can contain `np.nan`
            self.time   = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
            self.ref_X  = np.full(block_size, np.nan, dtype=np.float64)  # [V]
            self.ref_Y  = np.full(block_size, np.nan, dtype=np.float64)  # [V]
            self.sig_I  = np.full(block_size, np.nan, dtype=np.float64)  # [V]

            self.time_1 = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
            self.filt_I = np.full(block_size, np.nan, dtype=np.float64)  # [V]
            self.mix_X  = np.full(block_size, np.nan, dtype=np.float64)  # [V_RMS]
            self.mix_Y  = np.full(block_size, np.nan, dtype=np.float64)  # [V_RMS]

            self.time_2 = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
            self.X      = np.full(block_size, np.nan, dtype=np.float64)  # [V_RMS]
            self.Y      = np.full(block_size, np.nan, dtype=np.float64)  # [V_RMS]
            self.R      = np.full(block_size, np.nan, dtype=np.float64)  # [V_RMS]
            self.T      = np.full(block_size, np.nan, dtype=np.float64)  # [deg]

            self.sig_I_min  = np.nan  # [V]
            self.sig_I_max  = np.nan  # [V]
            self.sig_I_avg  = np.nan  # [V]
            self.sig_I_std  = np.nan  # [V]
            self.filt_I_min = np.nan  # [V]
            self.filt_I_max = np.nan  # [V]
            self.filt_I_avg = np.nan  # [V]
            self.filt_I_std = np.nan  # [V]
            self.X_avg      = np.nan  # [V_RMS]
            self.Y_avg      = np.nan  # [V_RMS]
            self.R_avg      = np.nan  # [V_RMS]
            self.T_avg      = np.nan  # [deg]
            # fmt: on

            # Ring buffers (rb) for performing FIR filtering and power spectra
            # fmt: off
            """
            Each time a complete block of `block_size` samples is received from
            the lock-in, it will extend the ring buffer array (FIFO shift
            buffer) with that block.

                i.e. N_blocks = 3
                    startup         : rb = [no value; no value ; no value]
                    received block 1: rb = [block_1 ; no value ; no value]
                    received block 2: rb = [block_1 ; block_2  ; no value]
                    received block 3: rb = [block_1 ; block_2  ; block_3]
                    received block 4: rb = [block_2 ; block_3  ; block_4]
                    received block 5: rb = [block_3 ; block_4  ; block_5]
                    etc...
            """
            p = {'capacity': self.rb_capacity, 'dtype': np.float64}

            # Stage 0: unprocessed data
            self.rb_time   = RingBuffer(**p)
            self.rb_ref_X  = RingBuffer(**p)
            self.rb_ref_Y  = RingBuffer(**p)
            self.rb_sig_I  = RingBuffer(**p)

            # Stage 1: AC-coupling and band-stop filter and heterodyne mixing
            self.rb_time_1 = RingBuffer(**p)
            self.rb_filt_I = RingBuffer(**p)
            self.rb_mix_X  = RingBuffer(**p)
            self.rb_mix_Y  = RingBuffer(**p)

            # Stage 2: low-pass filter and signal reconstruction
            self.rb_time_2 = RingBuffer(**p)
            self.rb_X      = RingBuffer(**p)
            self.rb_Y      = RingBuffer(**p)
            self.rb_R      = RingBuffer(**p)
            self.rb_T      = RingBuffer(**p)
            # fmt: on

            self.ringbuffers = [
                self.rb_time,
                self.rb_ref_X,
                self.rb_ref_Y,
                self.rb_sig_I,
                self.rb_time_1,
                self.rb_filt_I,
                self.rb_mix_X,
                self.rb_mix_Y,
                self.rb_time_2,
                self.rb_X,
                self.rb_Y,
                self.rb_R,
                self.rb_T,
            ]

            # Mutex for proper multithreading. If the state variables are not
            # atomic or thread-safe, you should lock and unlock this mutex for
            # each read and write operation.
            self.mutex = QtCore.QMutex()
コード例 #16
0
    def __init__(self, block_size, N_blocks):
        """Reflects the actual readings, parsed into separate variables, of
        the lock-in amplifier. There should only be one instance of the
        State class.
        """
        # fmt: off
        self.block_size = block_size
        self.N_blocks = N_blocks
        self.rb_capacity = block_size * N_blocks
        self.blocks_received = 0

        # Arrays to hold the block data coming from the lock-in amplifier
        # Keep `time` as `dtype=np.float64`, because it can contain `np.nan`
        self.time = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
        self.ref_X = np.full(block_size, np.nan, dtype=np.float64)
        self.ref_Y = np.full(block_size, np.nan, dtype=np.float64)
        self.sig_I = np.full(block_size, np.nan, dtype=np.float64)

        self.time_1 = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
        self.filt_I = np.full(block_size, np.nan, dtype=np.float64)
        self.mix_X = np.full(block_size, np.nan, dtype=np.float64)
        self.mix_Y = np.full(block_size, np.nan, dtype=np.float64)

        self.time_2 = np.full(block_size, np.nan, dtype=np.float64)  # [ms]
        self.X = np.full(block_size, np.nan, dtype=np.float64)
        self.Y = np.full(block_size, np.nan, dtype=np.float64)
        self.R = np.full(block_size, np.nan, dtype=np.float64)
        self.T = np.full(block_size, np.nan, dtype=np.float64)

        self.sig_I_min = np.nan
        self.sig_I_max = np.nan
        self.sig_I_avg = np.nan
        self.sig_I_std = np.nan
        self.filt_I_min = np.nan
        self.filt_I_max = np.nan
        self.filt_I_avg = np.nan
        self.filt_I_std = np.nan
        self.X_avg = np.nan
        self.Y_avg = np.nan
        self.R_avg = np.nan
        self.T_avg = np.nan

        # Ring buffers (rb) for performing FIR filtering and power spectra
        _p = {'capacity': self.rb_capacity, 'dtype': np.float64}

        # Stage 0: unprocessed data
        self.rb_time = RingBuffer(**_p)
        self.rb_ref_X = RingBuffer(**_p)
        self.rb_ref_Y = RingBuffer(**_p)
        self.rb_sig_I = RingBuffer(**_p)

        # Stage 1: AC-coupling and band-stop filter and heterodyne mixing
        self.rb_time_1 = RingBuffer(**_p)
        self.rb_filt_I = RingBuffer(**_p)
        self.rb_mix_X = RingBuffer(**_p)
        self.rb_mix_Y = RingBuffer(**_p)

        # Stage 2: apply low-pass filter and signal reconstruction
        self.rb_time_2 = RingBuffer(**_p)
        self.rb_X = RingBuffer(**_p)
        self.rb_Y = RingBuffer(**_p)
        self.rb_R = RingBuffer(**_p)
        self.rb_T = RingBuffer(**_p)
コード例 #17
0
    def test_addresses(self):
        r = RingBuffer(5)
        r.extend([1, 2, 3])
        np.testing.assert_equal(r, np.array([1, 2, 3]))
        self.assertNotEqual(r.current_address, r.unwrap_address)

        r.popleft()
        r.extend([4, 5, 6])
        np.testing.assert_equal(r, np.array([2, 3, 4, 5, 6]))
        self.assertEqual(r.current_address, r.unwrap_address)

        r.extendleft([0, 1])
        np.testing.assert_equal(r, np.array([0, 1, 2, 3, 4]))
        self.assertEqual(r.current_address, r.unwrap_address)

        r.extendleft([1, 2, 3, 4, 5, 6, 7])
        np.testing.assert_equal(r, np.array([1, 2, 3, 4, 5]))
        self.assertEqual(r.current_address, r.unwrap_address)

        r.extend([1, 2, 3, 4, 5, 6, 7])
        np.testing.assert_equal(r, np.array([3, 4, 5, 6, 7]))
        self.assertEqual(r.current_address, r.unwrap_address)

        r.clear()
        np.testing.assert_equal(r, np.array([]))
        np.testing.assert_equal(len(r), 0)
        self.assertNotEqual(r.current_address, r.unwrap_address)
コード例 #18
0
class ThreadSafeCurve(object):
    """Provides the base class for a thread-safe plot *curve* to which
    (x, y)-data can be safely appended or set from out of any thread. It
    will wrap around the passed argument ``linked_curve`` of type
    ``pyqtgraph.PlotDataItem`` and will manage the (x, y)-data buffers
    underlying the curve.

    Intended multi-threaded operation: One or more threads push new data
    into the ``ThreadSafeCurve``-buffers. Another thread performs the GUI
    refresh by calling ``update()`` which will redraw the curve according
    to the current buffer contents.

    Args:
        capacity (``int``, optional):
            When an integer is supplied it defines the maximum number op points
            each of the x-data and y-data buffers can store. The x-data buffer
            and the y-data buffer are each a ring buffer. New readings are
            placed at the end (right-side) of the buffer, pushing out the oldest
            readings when the buffer has reached its maximum capacity (FIFO).
            Use methods ``appendData()`` and ``extendData()`` to push in new
            data.

            When ``None`` is supplied the x-data and y-data buffers are each a
            regular array buffer of undefined length. Use method ``setData()``
            to set the data.

        linked_curve (``pyqtgraph.PlotDataItem``):
            Instance of ``pyqtgraph.PlotDataItem`` to plot the buffered
            data out into.

        shift_right_x_to_zero (``bool``, optional):
            When plotting, should the x-data be shifted such that the
            right-side is always set to 0? Useful for history charts.

            Default: False

        use_ringbuffer (``bool``, deprecated):
            Deprecated since v3.1.0. Defined for backwards compatibility.
            Simply supply a value for ``capacity`` to enable use of a ring
            buffer.

    Attributes:
        x_axis_divisor (``float``):
            The x-data in the buffer will be divided by this factor when the
            plot curve is drawn. Useful to, e.g., transform the x-axis units
            from milliseconds to seconds or minutes.

            Default: 1

        y_axis_divisor (``float``):
            Same functionality as ``x_axis_divisor``.

            Default: 1
    """
    def __init__(
        self,
        capacity: Optional[int],
        linked_curve: pg.PlotDataItem,
        shift_right_x_to_zero: bool = False,
        use_ringbuffer=None,  # Deprecated arg for backwards compatibility # pylint: disable=unused-argument
    ):
        self.capacity = capacity
        self.curve = linked_curve
        self.opts = self.curve.opts  # Use for read-only

        self._shift_right_x_to_zero = shift_right_x_to_zero
        self._use_ringbuffer = capacity is not None
        self._mutex = QtCore.QMutex()  # To allow proper multithreading

        self.x_axis_divisor = 1
        self.y_axis_divisor = 1

        if self._use_ringbuffer:
            self._buffer_x = RingBuffer(capacity=capacity)
            self._buffer_y = RingBuffer(capacity=capacity)
        else:
            self._buffer_x = np.array([])
            self._buffer_y = np.array([])

        self._snapshot_x = np.array([])
        self._snapshot_y = np.array([])

    def appendData(self, x, y):
        """Append a single (x, y)-data point to the ring buffer.
        """
        if self._use_ringbuffer:
            locker = QtCore.QMutexLocker(self._mutex)
            self._buffer_x.append(x)
            self._buffer_y.append(y)
            locker.unlock()

    def extendData(self, x_list, y_list):
        """Extend the ring buffer with a list of (x, y)-data points.
        """
        if self._use_ringbuffer:
            locker = QtCore.QMutexLocker(self._mutex)
            self._buffer_x.extend(x_list)
            self._buffer_y.extend(y_list)
            locker.unlock()

    def setData(self, x_list, y_list):
        """Set the (x, y)-data of the regular array buffer.
        """
        if not self._use_ringbuffer:
            locker = QtCore.QMutexLocker(self._mutex)
            self._buffer_x = x_list
            self._buffer_y = y_list
            locker.unlock()

    def update(self, create_snapshot: bool = True):
        """Update the data behind the curve by creating a snapshot of the
        current contents of the buffer, and redraw the curve on screen.

        Args:
            create_snapshot (``bool``):
                You can suppress updating the data behind the curve by setting
                this parameter to False. The curve will then only be redrawn
                based on the old data. This is useful when the plot is paused.

                Default: True
        """

        # Create a snapshot of the currently buffered data. Fast operation.
        if create_snapshot:
            locker = QtCore.QMutexLocker(self._mutex)
            self._snapshot_x = np.copy(self._buffer_x)
            self._snapshot_y = np.copy(self._buffer_y)
            # print("numel x: %d, numel y: %d" %
            #      (self._snapshot_x.size, self._snapshot_y.size))
            locker.unlock()

        # Now update the data behind the curve and redraw it on screen.
        # Note: .setData() will internally emit a PyQt signal to redraw the
        # curve, once it has updated its data members. That's why .setData()
        # returns almost immediately, but the curve still has to get redrawn by
        # the Qt event engine, which will happen automatically, eventually.
        if len(self._snapshot_x) == 0:
            self.curve.setData([], [])
        else:
            x_0 = self._snapshot_x[-1] if self._shift_right_x_to_zero else 0
            x = (self._snapshot_x - x_0) / float(self.x_axis_divisor)
            y = self._snapshot_y / float(self.y_axis_divisor)
            # self.curve.setData(x,y)  # No! Read below.

            # PyQt5 >= 5.12.3 causes a bug in PyQtGraph where a curve won't
            # render if it contains NaNs (but only in the case when OpenGL is
            # disabled). See for more information:
            # https://github.com/pyqtgraph/pyqtgraph/pull/1287/commits/5d58ec0a1b59f402526e2533977344d043b306d8
            #
            # My approach is slightly different:
            # NaN values are allowed in the source x and y arrays, but we need
            # to filter them such that the drawn curve is displayed as
            # *fragmented* whenever NaN is encountered. The parameter `connect`
            # will help us out here.
            # NOTE: When OpenGL is used to paint the curve by setting
            #   pg.setConfigOptions(useOpenGL=True)
            #   pg.setConfigOptions(enableExperimental=True)
            # the `connect` argument will get ignored and the curve fragments
            # are connected together into a continuous curve, linearly
            # interpolating the gaps. Seems to be little I can do about that,
            # apart from modifying the pyqtgraph source-code in
            # `pyqtgraph.plotCurveItem.paintGL()`.
            #
            # UPDATE 07-08-2020:
            # Using parameter `connect` as used below will cause:
            #   ValueError: could not broadcast input array from shape ('N') into shape ('< N')
            #   --> arr[1:-1]['c'] = connect
            #   in ``pyqtgraph.functinos.arrayToQPath()``
            # This happens when ClipToView is enabled and the curve data extends
            # past the viewbox limits, when not using OpenGL.
            # We simply comment out those lines. This results in 100% working
            # code again, though the curve is no longer shown fragmented but
            # continuous (with linear interpolation) at each NaN value. That's
            # okay.

            finite = np.logical_and(np.isfinite(x), np.isfinite(y))
            # connect = np.logical_and(finite, np.roll(finite, -1))
            x_finite = x[finite]
            y_finite = y[finite]
            # connect = connect[finite]

            self.curve.setData(x_finite, y_finite)  # , connect=connect)

    @QtCore.pyqtSlot()
    def clear(self):
        """Clear the contents of the curve and redraw.
        """
        locker = QtCore.QMutexLocker(self._mutex)
        if self._use_ringbuffer:
            self._buffer_x.clear()
            self._buffer_y.clear()
        else:
            self._buffer_x = np.array([])
            self._buffer_y = np.array([])
        locker.unlock()

        self.update()

    def name(self):
        """Get the name of the curve.
        """
        return self.curve.name()

    def isVisible(self) -> bool:
        return self.curve.isVisible()

    def setVisible(self, state: bool = True):
        self.curve.setVisible(state)

    def setDownsampling(self, *args, **kwargs):
        """All arguments will be passed onto method
        ``pyqtgraph.PlotDataItem.setDownsampling()`` of the underlying curve.
        """
        self.curve.setDownsampling(*args, **kwargs)

    @property
    def size(self) -> Tuple[int, int]:
        """Number of elements currently contained in the underlying (x, y)-
        buffers of the curve. Note that this is not necessarily the number of
        elements of the currently drawn curve. Instead, it reflects the current
        sizes of the data buffers behind it that will be drawn onto screen by
        the next call to ``update()``.
        """
        # fmt: off
        locker = QtCore.QMutexLocker(self._mutex)  # pylint: disable=unused-variable
        # fmt: on
        return (len(self._buffer_x), len(self._buffer_y))
コード例 #19
0
# -----------------------------------------

# Optimal scenario:
#   Perform convolve every incoming buffer
#   Maximize N_taps given N_BLOCKS
BLOCK_SIZE = 500  # [samples]
N_BLOCKS = 41

# Ring buffers
rb_capacity = BLOCK_SIZE * N_BLOCKS

if False:
    rb_time = deque(maxlen=rb_capacity)
    rb_sig_I = deque(maxlen=rb_capacity)
else:
    rb_time = RingBuffer(capacity=rb_capacity)
    rb_sig_I = RingBuffer(capacity=rb_capacity)

config = RingBuffer_FIR_Filter_Config(
    Fs=Fs,
    block_size=BLOCK_SIZE,
    N_blocks=N_BLOCKS,
    firwin_cutoff=[49, 51],
    firwin_window="blackmanharris",
    firwin_pass_zero=True,
    use_CUDA=False,
)

firf = RingBuffer_FIR_Filter(config=config)
firf.report()