1

我正在尝试使用 Vispy 实时获取和显示信号。我通过 pyserial 通过串行端口获取信号。

我已经修改了 realtime_signals 示例(https://github.com/vispy/vispy/blob/master/examples/demo/gloo/realtime_signals.py)并且能够单独显示每个信号。我还可以显示相同信号的 3 或 5 个图。但我无法在同一画布或插入 PyQt5 应用程序的两个不同画布中显示两个信号(每个来自不同的串行端口)。我对 OpenGL 和着色器没有经验。

串口代码和修改后的场景定时器代码如下。

#import multiprocessing
from PyQt5.QtWidgets import *
import vispy.app
import sys


from vispy import gloo
from vispy import app
import numpy as np
import math
import serial

datam=0.0
seri=serial.Serial("/dev/ttyACM0", baudrate=115200, timeout=1)
class Seriport(serial.Serial):
    def oku():
        global datam

        while seri.isOpen:
            dataGet=''
            serialData = seri.read().decode('ascii')
            if serialData == '$':
                while not serialData == ';':
                    serialData = seri.read().decode('ascii')
                    if not serialData == ';':
                        dataGet += serialData
            if not '$' in dataGet:
                dataList = dataGet.split(',')
                if len(dataList) == 3:
                    datam=float(dataList[0])-125000

            print(datam)
            return datam


# Number of cols and rows in the table.
nrows = 3
ncols = 1

# Number of signals.x = np.arange(sample)
m = nrows*ncols

# Number of samples per signal.
n = 1000

# Various signal amplitudes.

amplitudes = .1 + .2 * np.random.rand(m, 1).astype(np.float32)

# Generate the signals as a (m, n) array.
# y = amplitudes * np.random.randn(m, n).astype(np.float32)

y = np.zeros([m, n], dtype = np.float32) 

# Color of each vertex (TODO: make it more efficient by using a GLSL-based
# color map and the index).

color = np.repeat(np.random.uniform(size=(m, 3), low=.5, high=.9),
                n, axis=0).astype(np.float32)

# Signal 2D index of each vertex (row and col) and x-index (sample index
# within each signal).
index = np.c_[np.repeat(np.repeat(np.arange(ncols), nrows), n),
              np.repeat(np.tile(np.arange(nrows), ncols), n),
              np.tile(np.arange(n), m)].astype(np.float32)

VERT_SHADER = """
#version 120
// y coordinate of the position.
attribute float a_position;
// row, col, and time index.
attribute vec3 a_index;
varying vec3 v_index;
// 2D scaling factor (zooming).
uniform vec2 u_scale;
// Size of the table.
uniform vec2 u_size;
// Number of samples per signal.
uniform float u_n;
// Color.
attribute vec3 a_color;
varying vec4 v_color;
// Varying variables used for clipping in the fragment shader.
varying vec2 v_position;
varying vec4 v_ab;
void main() {
    float nrows = u_size.x;
    float ncols = u_size.y;
    // Compute the x coordinate from the time index.
    float x = -1 + 2*a_index.z / (u_n-1);
    vec2 position = vec2(x - (1 - 1 / u_scale.x), a_position);
    // Find the affine transformation for the subplots.
    vec2 a = vec2(1./ncols, 1./nrows)*.9;
    vec2 b = vec2(-1 + 2*(a_index.x+.5) / ncols,
                  -1 + 2*(a_index.y+.5) / nrows);
    // Apply the static subplot transformation + scaling.
    gl_Position = vec4(a*u_scale*position+b, 0.0, 1.0);
    v_color = vec4(a_color, 1.);
    v_index = a_index;
    // For clipping test in the fragment shader.
    v_position = gl_Position.xy;
    v_ab = vec4(a, b);
}
"""

FRAG_SHADER = """
#version 120
varying vec4 v_color;
varying vec3 v_index;
varying vec2 v_position;
varying vec4 v_ab;
void main() {
    gl_FragColor = v_color;
    // Discard the fragments between the signals (emulate glMultiDrawArrays).
    if ((fract(v_index.x) > 0.) || (fract(v_index.y) > 0.))
        discard;
    // Clipping test.
    vec2 test = abs((v_position.xy-v_ab.zw)/v_ab.xy);
    if ((test.x > 1) || (test.y > 1))
        discard;
}
"""



class Canvas(app.Canvas):

    def __init__(self):
        app.Canvas.__init__(self, title='Use your wheel to zoom!',
                            keys='interactive')
        self.program = gloo.Program(VERT_SHADER, FRAG_SHADER)
        self.program['a_position'] = y.reshape(-1, 1)
        self.program['a_color'] = color
        self.program['a_index'] = index
        self.program['u_scale'] = (1., 1.)
        self.program['u_size'] = (nrows, ncols)
        self.program['u_n'] = n

        gloo.set_viewport(0, 0, *self.physical_size)

        self._timer = app.Timer(0.001, connect=self.on_timer, start=True)

        gloo.set_state(clear_color='black', blend=True,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))

        self.show()

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.physical_size)

    def on_mouse_wheel(self, event):
        dx = np.sign(event.delta[1]) * .05
        scale_x, scale_y = self.program['u_scale']
        scale_x_new, scale_y_new = (scale_x * math.exp(2.5*dx),
                                    scale_y * math.exp(0.0*dx))
        self.program['u_scale'] = (max(1, scale_x_new), max(1, scale_y_new))
        self.update()

    def on_timer(self, event):
        """Add some data at the end of each signal (real-time signals)."""
        global datam
        k = 1
        y[:, :-k] = y[:, k:]
        # y[:, -k:] = datam/50000

        y[:, -k:] = (Seriport.oku()/5000)

        # y[:, -k:] = amplitudes * np.random.randn(m, k)

        self.program['a_position'].set_data(y.ravel().astype(np.float32))
        self.update()

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('line_strip')


canvas = Canvas()

w = QMainWindow()

widget = QWidget()
frame = QFrame()

w.setCentralWidget(widget)
widget.setLayout(QHBoxLayout())

frame.setLayout(QVBoxLayout())

widget.layout().addWidget(canvas.native)
#widget.layout().addWidget(canvas2.native)

widget.layout().addWidget(frame)
frame.layout().addWidget(QPushButton())
frame.layout().addWidget(QPushButton())
frame.layout().addWidget(QPushButton())
frame.layout().addWidget(QPushButton())
frame.layout().addWidget(QPushButton())
w.show()

vispy.app.run()
def on_timer(self, event):
        """Add some data at the end of each signal (real-time signals)."""
        global datam
        k = 1
        y[:, :-k] = y[:, k:]
        # y[:, -k:] = datam/50000

        y[:, -k:] = (Seriport.oku()/5000)

        # y[:, -k:] = amplitudes * np.random.randn(m, k)

        self.program['a_position'].set_data(y.ravel().astype(np.float32))
        self.update()

任何帮助,将不胜感激。

4

0 回答 0