I wanted to add plots to GraphicsLayoutWidget. However i tried with the code i have written which is below.
But now i wanted to changed i have two types of msgs one in live mode and in other recorded mode.
However i wanted to add one more plot item in live mode.
To be sure i also added some comments in the code to get some understanding for you.I only pasted some part of the code.
I searched already in stack but couldnt find answers which solves my thing.
from pyqtgraph.Qt import QtCore, QtGui
import threading
import pyqtgraph as pg
import socket
import psutil
import time
import struct
import sys
import collections
import os
import PySimpleGUI as sg
import easygui
visualize_recorded_msg = 1
driver_called_from_outside = 0
BufferLength = 500
marker_size = 14
if 0 == visualize_recorded_msg:
if 0 == driver_called_from_outside:
driver_name = 'sss'
else:
name_of_the_recorded_file = 'sss.bin'
########################################################################################################################
def get_pid_and_kill(process_name):
for proc in psutil.process_iter():
if proc.name() == process_name:
p = psutil.Process(proc.pid)
p.terminate()
print("Process " + process_name + " terminated")
if 0 == visualize_recorded_msg:
if 0 == driver_called_from_outside:
from subprocess import Popen
get_pid_and_kill(driver_name.split(("/"))[-1])
get_pid_and_kill(driver_name.split(("\\"))[-1])
get_pid_and_kill("cmd.exe")
Popen([driver_name])
print("The driver started")
time.sleep(1)
# TCP/IP Socket creation
HOST = '145.0.0.10'
PORT = 8085
try:
socket_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_connection.settimeout(3)
socket_connection.connect((HOST, PORT))
socket_connection.settimeout(None)
print("Socket successfully created")
except socket.error as err:
raise SystemExit("Socket creation failed with error %s" % err)
else:
file_handle = open(name_of_the_recorded_file, 'rb')
all_msgs = file_handle.read()
file_handle.close()
def open_exit_button():
even_name = 'kill the driver'
layout = [[sg.Button(even_name, button_color=('white', 'springgreen4'))]]
window = sg.Window('Configurations', layout)
while True: # Event Loop
event, values = window.read(timeout=10)
if event == sg.WIN_CLOSED or event == even_name:
if 0 == visualize_recorded_msg:
get_pid_and_kill(driver_name.split(("/"))[-1])
get_pid_and_kill(driver_name.split(("\\"))[-1])
os._exit(1)
break
window.close()
class Visualizer(object):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.view = pg.GraphicsLayoutWidget()
self.view.setWindowTitle('')
self.w1 = self.view.addPlot(row=0, col=0, title='Accelerometer 1')
self.w1.showGrid(x=True, y=True)
self.w1.addLegend()
self.w1.setLabel(axis='bottom', text='Time [s]')
self.w1.setLabel(axis='left', text='')
self.w1.curve2 = self.w1.plot(name='')
self.w1.curve3 = self.w1.plot(name='')
self.w2 = self.view.addPlot(row=1, col=0, title='')
self.w2.showGrid(x=True, y=True)
self.w2.addLegend()
self.w2.setLabel(axis='bottom', text='Time [s]')
self.w2.setLabel(axis='left', text='')
self.w2.curve2 = self.w2.plot(name='')
self.w2.curve3 = self.w2.plot(name='')
self.w3 = self.view.addPlot(row=2, col=0, title='Average')
self.w3.showGrid(x=True, y=True)
self.w3.setLabel(axis='bottom', text='Time [s]')
self.w3.setLabel(axis='left', text='')
self.w3.curve1 = self.w3.plot()
self.w4 = self.view.addPlot(row=3, col=0, title='result ')
self.w4.showGrid(x=True, y=True)
self.w4.setLabel(axis='bottom', text='Time [s]')
self.w4.setLabel(axis='left', text='')
self.w4.curve1 = self.w4.plot()
self.a = collections.deque(maxlen=BufferLength)
self.b = collections.deque(maxlen=BufferLength)
self.c = collections.deque(maxlen=BufferLength)
self.d = collections.deque(maxlen=BufferLength)
self.e = collections.deque(maxlen=BufferLength)
self.f = collections.deque(maxlen=BufferLength)
self.view.show()
self.prevFrameCnt = 0
self.iteration_index = 0
self.li_det = 0
self.str_mot = 1
#staticmethod
def start():
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
def message_parser(self, data):
out1 = struct.unpack("<L", data[0:4])[0]
out2 = data[4]
out3 = data[5]
out4 = data[6]
out5 = struct.unpack("<h", data[7:9])[0]
out6 = struct.unpack("<H", data[9:11])[0]
out7 = struct.unpack("<H", data[11:13])[0]
out8 = struct.unpack("<H", data[17:19])[0]
out9 = struct.unpack("<H", data[19:21])[0]
return [out1, out2, out3, out4, out5, out6, out7, out8, out9]
def update(self):
if 0 == visualize_recorded_msg:
# Receive TCP/IP packet
try:
data = socket_connection.recv(64)
except socket.timeout as e:
print(e)
return
except (ConnectionResetError, OSError):
raise SystemExit("Remote server closed")
# Decode TCP/IP packet
output = self.message_parser(data)
else:
msg_length = 21
try:
data = all_msgs[self.iteration_index: self.iteration_index + msg_length]
decode_output = self.message_parser(data)
self.iteration_index += msg_length
except:
print('End of file')
x = decode_output[0]
y = decode_output[4]
z = decode_output[5]
x1 = decode_output[6]
y1 = decode_output[7]
z1 = decode_output[8]
if self.prevFrameCnt == x:
MovDet = decode_output[1]
LiDet = decode_output[2]
MotDet = decode_output[3]
self.a.append(y)
self.c.append(z1)
self.d.append(y1)
self.w2.curve2.setData(self.c, pen=None, symbol='t', symbolPen=None, symbolSize=marker_size,
symbolBrush=(0, 114, 189))
self.w2.curve3.setData(self.d, pen=None, symbol='t1', symbolPen=None, symbolSize=marker_size,
symbolBrush=(217, 83, 25))
self.w3.curve1.setData(self.a, pen=None, symbol='d', symbolPen=None, symbolSize=marker_size,
symbolBrush=('g'))
self.w4.curve1.setData(self.f, pen=None, symbol='o', symbolPen=None,
symbolSize=marker_size,
symbolBrush=(217, 83, 25))
if (1 == self.li_det) or (105 == LiDet):
self.li_det = 1
else:
MovDet = decode_output[1]
LiDet = decode_output[2]
MotDet = decode_output[3]
self.b.append(z1)
self.d.append(y1)
self.w1.curve2.setData(self.b, pen=None, symbol='t', symbolPen=None, symbolSize=marker_size,
symbolBrush=(0, 114, 189))
self.w1.curve3.setData(self.d, pen=None, symbol='t1', symbolPen=None, symbolSize=marker_size,
symbolBrush=(217, 83, 25))
self.prevFrameCnt = x
self.view.show()
def animation(self):
timer = QtCore.QTimer()
timer.timeout.connect(self.update)
timer.start(1)
self.start()
def visualization():
v = Visualizer()
v.animation()
def main():
if 0 == driver_called_from_outside:
thread = threading.Thread(target=visualization)
thread.start()
open_exit_button()
else:
visualization()
if __name__ == '__main__':
main()
Related
Referring to:
How to pass parameters to PyQt QThreadPool running function
I am trying to apply the above topic to my code to avoid GUI freezing, the issue that fails to create a pushbutton within the TableWedgit in fn(push) and (setCellWidget) when using the fn(Run) when pressing "PushButton", while it is fine with fn(run) when pressing"RadioButton" with a GUI freezing.
All the files are available via the link:
https://drive.google.com/file/d/1fE7NkX9y1SFTHDuZWZZxh_NiL-msiZbT/view?usp=sharing
import os
import sys
import traceback
from time import sleep
import openpyxl
import pandas
import pandas as pd
import xlsxwriter
from PyQt5 import QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from openpyxl import load_workbook
from loop_150 import Ui_Form
class WorkerSignals(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(int)
class Worker(QRunnable):
def __init__(self, fn):
super(Worker, self).__init__()
self.fn = fn
self.signals = WorkerSignals()
#pyqtSlot()
def run(self):
try:
result = self.fn()
except Exception as e:
print('Worker(QRunnable):', e)
class PushButton(QtWidgets.QPushButton):
def __init__(self, object_name):
super(PushButton, self).__init__()
self.setObjectName(str(object_name))
class Form(QWidget, Ui_Form):
def __init__(self):
QWidget.__init__(self)
self.setupUi(self)
self.radioButton.clicked.connect(self.run)
self.pushButton.clicked.connect(self.Run)
self.tableWidget_1.itemChanged.connect(self.ItemChanged)
self.threadpool = QThreadPool()
def run(self):
df0 = self.excel_to_df('trade_ratio_dffx0')
df1 = self.excel_to_df('trade_ratio_dffx1')
df2 = self.excel_to_df('trade_ratio_dffx2')
df3 = self.excel_to_df('trade_ratio_dffx3')
i = 0
x = 0
y =1
z =2
m = 3
self.previous_item = []
while i < 10:
self.textBrowser.append(str(i))
app.processEvents()
sleep(1)
if i == x:
df = df3
if i == y:
df = df1
if i == z:
df = df2
if i == m:
df = df0
x += 4
y += 4
z += 4
m += 4
i += 1
table = self.tableWidget_1
self.table_view(df, table)
self.push()
self.previous_item = []
for items in df['balance']:
self.previous_item.append(items)
app.processEvents()
def Run(self):
worker = Worker(self.run)
self.threadpool.start(worker)
def push(self):
try:
for row in range(1, self.tableWidget_1.rowCount()):
pushButton = PushButton(row)
self.tableWidget_1.setCellWidget(row, 3, pushButton)
r = self.tableWidget_1.item(row, 3).text()
if float(r) > 0:
pushButton.setStyleSheet("background:rgb(0, 188, 138);color:rgb(255, 255, 255)")
elif float(r) == 0:
pushButton.setStyleSheet("background:rgb(185, 185, 185);color:rgb(255, 255, 255)")
else:
pushButton.setStyleSheet("background:rgb(255, 5, 72);color:rgb(255, 255, 255)")
pushButton.setText(r + '%')
except Exception as e:
print('push', e)
def ItemChanged(self, item):
try:
for row in range(1, self.tableWidget_1.rowCount()):
if item.column() == 1 and self.tableWidget_1.item(row, 1).text() != None:
if float(self.tableWidget_1.item(row, 1).text()) < 0:
self.tableWidget_1.item(row, 1).setForeground(QColor(255, 0, 100, 200))
elif float(self.tableWidget_1.item(row, 1).text()) > 0:
self.tableWidget_1.item(row, 1).setForeground(QColor(0, 222, 122, 222))
elif float(self.tableWidget_1.item(row, 1).text()) == 0:
self.tableWidget_1.item(row, 1).setForeground(QColor(0, 0, 0, 150))
except:
pass
def excel_to_df(self, wbkName):
while True:
try:
wbkName = wbkName + ".xlsx"
df = pd.read_excel(wbkName)
try:
df = df.drop(columns=['Index'])
except:
pass
try:
df = df.drop(columns=['index'])
except:
pass
try:
df = df.drop(columns=[0])
except:
pass
try:
df = df.drop(columns=['Unnamed: 0'])
except:
pass
try:
df = df.drop(columns=['Unnamed'])
except:
pass
try:
df = df.drop(columns=['0'])
except:
pass
try:
df = df.drop(columns=['Unnamed:'])
except:
pass
return df
except:
pass
def table_view(self, df, table):
col_number = len(df.columns)
table.setColumnCount(col_number)
table.setRowCount(0)
table.insertRow(0)
for row_number in range(len(df)):
table.insertRow(row_number + 1)
for col_number, col_data in enumerate(df):
table.setItem(0, col_number, QtWidgets.QTableWidgetItem(str(col_data)))
table.setItem(row_number + 1, col_number, QtWidgets.QTableWidgetItem(str(df[col_data][row_number])))
header = table.horizontalHeader()
header.setSectionResizeMode(col_number, QtWidgets.QHeaderView.Stretch)
app = QApplication(sys.argv)
window = Form()
window.show()
app.exec_()
I am trying to update plot with new data points. But the problem i am having is it is slow. I am using draw_now may be that is the problem as per this stack question: why is plotting with Matplotlib so slow?
I tried that approaches mentioned in that question and i still have same problems.
I recieve data from accelerometer and i take that data to update my plots.
from pyqtgraph.Qt import QtCore, QtGui
import threading
import pyqtgraph as pg
import socket
import psutil
import time
import struct
import sys
import collections
import os
import PySimpleGUI as sg
import easygui
import matplotlib.pyplot as plt
from mpl_toolkits
import mplot3d
BufferLength = 500 marker_size = 14
driver_name = 'sss.exe'
def get_pid_and_kill(process_name):
for proc in psutil.process_iter():
if proc.name() == process_name:
p = psutil.Process(proc.pid)
p.terminate()
print("Process " + process_name + " terminated") def run_the_driver(driver_exe_name):
from subprocess import Popen
get_pid_and_kill(driver_exe_name.split("/")[-1])
get_pid_and_kill(driver_exe_name.split("\\")[-1])
get_pid_and_kill("cmd.exe")
Popen([driver_exe_name])
time.sleep(3)
def create_tcp_ip_socket():
HOST = '145.0.0.1'
PORT = 7060
try:
socket_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_connection.settimeout(3)
socket_connection.connect((HOST, PORT))
socket_connection.settimeout(1)
print("Socket Successfully created")
except socket.error as err:
raise SystemExit("Socket creation failed with error %s" % err)
def open_exit_button():
even_name = 'kill the driver'
layout = [[sg.Button(even_name, button_color=('white', 'springgreen4'))]]
window = sg.Window('Configurations', layout)
while True: # Event Loop
event, values = window.read(timeout=10)
if event == sg.WIN_CLOSED or event == even_name:
if 0 == visualize_recorded_msg:
get_pid_and_kill(driver_name.split(("/"))[-1])
get_pid_and_kill(driver_name.split(("\\"))[-1])
os._exit(1)
break
window.close()
class Visualizer(object):
def __init__(self):
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, projection="3d")
self.ax.set_title('3D Points')
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
self.ax.set_zlabel('Z')
self.ax.set_xlim(-2.5, 2.5)
self.ax.set_ylim(0, 3)
self.ax.set_zlim(-1.5, 1.5)
self.app = QtGui.QApplication(sys.argv)
self.view = pg.GraphicsLayoutWidget()
self.view.setWindowTitle('')
self.w1 = self.view.addPlot(row=0, col=0, title='Accelerometer 1')
self.w1.showGrid(x=True, y=True)
self.w1.addLegend()
self.w1.setLabel(axis='bottom', text='Time [s]')
self.w1.setLabel(axis='left', text='')
self.w1.curve2 = self.w1.plot(name='')
self.w1.curve3 = self.w1.plot(name='')
self.w2 = self.view.addPlot(row=1, col=0, title='')
self.w2.showGrid(x=True, y=True)
self.w2.addLegend()
self.w2.setLabel(axis='bottom', text='Time [s]')
self.w2.setLabel(axis='left', text='')
self.w2.curve2 = self.w2.plot(name='')
self.w2.curve3 = self.w2.plot(name='')
self.w3 = self.view.addPlot(row=2, col=0, title='Average')
self.w3.showGrid(x=True, y=True)
self.w3.setLabel(axis='bottom', text='Time [s]')
self.w3.setLabel(axis='left', text='')
self.w3.curve1 = self.w3.plot()
self.w4 = self.view.addPlot(row=3, col=0, title='result ')
self.w4.showGrid(x=True, y=True)
self.w4.setLabel(axis='bottom', text='Time [s]')
self.w4.setLabel(axis='left', text='')
self.w4.curve1 = self.w4.plot()
self.a = collections.deque(maxlen=BufferLength)
self.b = collections.deque(maxlen=BufferLength)
self.c = collections.deque(maxlen=BufferLength)
self.d = collections.deque(maxlen=BufferLength)
self.e = collections.deque(maxlen=BufferLength)
self.f = collections.deque(maxlen=BufferLength)
self.pos_x = collections.deque(maxlen=BufferLength)
self.pos_y = collections.deque(maxlen=BufferLength)
self.pos_z = collections.deque(maxlen=BufferLength)
self.pos_x_out = collections.deque(maxlen=BufferLength)
self.pos_y_out = collections.deque(maxlen=BufferLength)
self.pos_z_out = collections.deque(maxlen=BufferLength)
self.view.show()
self.fig.show()
self.fig.canvas.draw()
self.prevFrameCnt = 0
self.iteration_index = 0
self.li_det = 0
self.str_mot = 1
#staticmethod
def start():
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
def message_parser(self, data):
out1 = struct.unpack("<L", data[0:4])[0]
out2 = data[4]
out3 = data[5]
out4 = data[6]
out5 = struct.unpack("<h", data[7:9])[0]
out6 = struct.unpack("<H", data[9:11])[0]
out7 = struct.unpack("<H", data[11:13])[0]
out8 = struct.unpack("<H", data[17:19])[0]
out9 = struct.unpack("<H", data[19:21])[0]
out10 = struct.unpack("<H", data[19:21])[0]
out11 = struct.unpack("<H", data[21:23])[0]
out12 = struct.unpack("<H", data[23:25])[0]
return [out1, out2, out3, out4, out5, out6, out7, out8, out9,out10, out11, out12]
def update(self):
try:
data = socket_connection.recv(64)
except socket.timeout as e:
print(e)
except (ConnectionResetError, OSError):
raise SystemExit("server closed")
output = self.message_parser(data)
x = output[0]
y = output[4]
z = output[5]
x1 = output[6]
y1 = output[7]
z1 = output[8]
if self.prevFrameCnt == x:
MovDet = output[1]
LiDet = output[2]
MotDet = output[3]
self.a.append(y)
self.c.append(z1)
self.d.append(y1)
self.w2.curve2.setData(self.c, pen=None, symbol='t', symbolPen=None, symbolSize=marker_size,
symbolBrush=(0, 114, 189))
self.w2.curve3.setData(self.d, pen=None, symbol='t1', symbolPen=None, symbolSize=marker_size,
symbolBrush=(217, 83, 25))
self.w3.curve1.setData(self.a, pen=None, symbol='d', symbolPen=None, symbolSize=marker_size,
symbolBrush=('g'))
self.w4.curve1.setData(self.f, pen=None, symbol='o', symbolPen=None,
symbolSize=marker_size,
symbolBrush=(217, 83, 25))
if (1 == self.li_det) or (105 == LiDet):
self.li_det = 1
else:
MovDet = output[1]
LiDet = output[2]
MotDet = output[3]
pos_x = output[10]
pos_y = output[11]
pos_z = output[12]
is_in = pos_z 0.5
is_in = is_in and (pos_z < 0.6)
is_in = is_in and (pos_x < 0.7)
is_in = is_in and (pos_x 0.8)
is_in = is_in and (pos_y 0.7)
if is_in:
self.pos_x.append(pos_x)
self.pos_y.append(pos_x)
self.pos_z.append(pos_x)
self.ax.scatter3D(self.pos_x, self.pos_y, self.pos_z, color='green')
self.fig.canvas.draw_idle()
else:
self.pos_x_out.append(pos_x)
self.pos_y_out.append(pos_x)
self.pos_z_out.append(pos_x)
self.ax.scatter3D(self.pos_x_out, self.pos_y_out, self.pos_z_out, color='green')
self.fig.canvas.draw_idle()
#
self.b.append(z1)
self.d.append(y1)
self.w1.curve2.setData(self.b, pen=None, symbol='t', symbolPen=None, symbolSize=marker_size,
symbolBrush=(0, 114, 189))
self.w1.curve3.setData(self.d, pen=None, symbol='t1', symbolPen=None, symbolSize=marker_size,
symbolBrush=(217, 83, 25))
self.prevFrameCnt = x
self.view.show()
self.fig.show()
def animation(self):
timer = QtCore.QTimer()
timer.timeout.connect(self.update)
timer.start(1)
self.start()
def visualization():
v = Visualizer()
v.animation()
def main():
thread = threading.Thread(target=visualization)
thread.start()
open_exit_button()
if __name__ == '__main__':
main()
But problem is if i plot either matplot one or pyqt one it is working fast without any delay in FPS. But when i plot both then plot function is not that quickly updated in pyqt one?
Matplotlib is generally not so ideal for real time plotting based on several answers posted in different questions in stack Why Matplotlib is slow. So it is better to use vispy Vispy for real time plotting.
In my case, plotting with Vispy really solved the problem of updating the plots slow
I would like to add the ability to update a data field (number) on my current pyqt script. I was trying to use "addLabel" but I can't update their content dynamically.
Any suggestion on how to make it? I am using addPlot function to create the plots which will be processing some data from a UDP packet. In some cases, I want to just show the value dynamically. Not sure what will be the best widget to use for this purpose?
Current script:
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
from pyqtgraph.ptime import time
import struct
from struct import pack, unpack
import socket
app = QtGui.QApplication([])
data = []
data_throttle = []
data_brake = []
data_steering = []
data_state = []
data_error = []
pg.setConfigOption('background', (0,0,0))
#pg.setConfigOption(antialias=True)
win = pg.GraphicsWindow()
win.resize(500,200)
p1 = win.addPlot(title="Sequence")
p1.setWindowTitle('Sequence')
p1.setRange(QtCore.QRectF(0, 0, 100, 150))
#p1.setLabel('bottom', 'Packet', units=' ')
p1.showGrid(True, True)
p2 = win.addPlot(title="Throttle")
p2.setWindowTitle('Throttle')
p2.setRange(QtCore.QRectF(0, 0, 100, 255))
#p2.setLabel('bottom', 'Packet', units=' ')
p2.showGrid(True, True)
p3 = win.addPlot(title="Brake")
p3.setWindowTitle('Brake')
p3.setRange(QtCore.QRectF(0, 0, 100, 255))
#p3.setLabel('bottom', 'Packet', units=' ')
p3.showGrid(True, True)
p4 = win.addPlot(title="Steering")
p4.setWindowTitle('Steering')
p4.setRange(QtCore.QRectF(0, -1, 100, 2))
#p4.setLabel('bottom', 'Packet', units=' ')git
p4.showGrid(True, True)
p5 = win.addPlot(title="Vehicle State")
p5.setWindowTitle('Vehicle State')
p5.setRange(QtCore.QRectF(0, 0, 100, 10))
#p5.setLabel('bottom', 'Packet', units=' ')
p5.showGrid(True, True)
p6 = win.addPlot(title="Errors")
p6.setWindowTitle('Errors')
p6.setRange(QtCore.QRectF(0, 0, 100, 10))
#p6.setLabel('bottom', 'Packet', units=' ')
p6.showGrid(True, True)
top_label = "Percent"
bottom_label = "85"
l_labels = win.addLayout(col=1, colspan=1)
l_labels.addLabel(top_label, row=0, col=0, rowspan=1, colspan=1, size='30pt', bold=True)
l_labels.addLabel(bottom_label, row=2, col=0, rowspan=4, colspan=1, size='200pt', color='606060')
l_labels.setContentsMargins(0, 0, 0, 100)
curve = p1.plot(pen='r')
curve2 = p2.plot(pen='b')
curve3 = p3.plot(pen='g')
curve4 = p4.plot(pen='y')
curve5 = p5.plot(pen='r')
curve6 = p6.plot(pen='b')
# Receive UDP packets transmitted by a broadcasting service
RECEIVE_IP = ''
RECEIVE_PORT = 2337
RECEIVE_ADDRESS = (RECEIVE_IP, RECEIVE_PORT)
recv_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
recv_socket.bind(RECEIVE_ADDRESS)
JOY_CODE = '=HBBBhHQQB'
ACK_CODE = '=HHBBHBBhBqB'
ptr = 0
lastTime = time()
fps = None
def update():
global recv_socket, fScale
global curve, data, data_throttle, data_brake, data_steering, ptr, p, lastTime, fps, data_state, data_error
recv_message, address = recv_socket.recvfrom(22)
message_id, ack_payload, ack_seq, vehicle_state, vehicle_speed, throttle, brake, steering, error, timestamp, checksum = struct.unpack(ACK_CODE, recv_message)
#data = throttle
data.append(ack_seq)
data = data[-100:]
data_throttle.append(throttle)
data_throttle = data_throttle[-100:]
data_brake.append(brake)
data_brake = data_brake[-100:]
data_steering.append(steering / 32768)
data_steering = data_steering[-100:]
vehicle_state = vehicle_state & 0x07
data_state.append(vehicle_state)
data_state = data_state[-100:]
data_error.append(error)
data_error = data_error[-100:]
#print(throttle)
#print("got data", data, " ", lastTime, "\n")
# print data
#curve.setData(fScale,data,_callSync='off')
curve.setData(data,_callSync='off')
curve2.setData(data_throttle,_callSync='off')
curve3.setData(data_brake,_callSync='off')
curve4.setData(data_steering,_callSync='off')
curve5.setData(data_state, _callSync='off')
curve6.setData(data_error, _callSync='off')
bottom_label = vehicle_state
now = time()
dt = now - lastTime
lastTime = now
app.processEvents() ## force complete redraw for every plot
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
I was able to figure the solution by using TextItem inside a Plot
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
from pyqtgraph.ptime import time
import struct
from struct import pack, unpack
import socket
app = QtGui.QApplication([])
data = []
data_throttle = []
data_brake = []
data_steering = []
data_state = []
data_error = []
pg.setConfigOption('background', (0,0,0))
#pg.setConfigOption(antialias=True)
win = pg.GraphicsWindow()
win.resize(1600,1000)
p1 = win.addPlot(title="Sequence",row=0, col=1)
p1.setWindowTitle('Sequence')
p1.setRange(QtCore.QRectF(0, 0, 100, 150))
p1.showGrid(True, True)
p2 = win.addPlot(title="Throttle",row=0, col=2)
p2.setWindowTitle('Throttle')
p2.setRange(QtCore.QRectF(0, 0, 100, 255))
p2.showGrid(True, True)
p3 = win.addPlot(title="Brake",row=0, col=3)
p3.setWindowTitle('Brake')
p3.setRange(QtCore.QRectF(0, 0, 100, 255))
p3.showGrid(True, True)
p4 = win.addPlot(title="Steering",row=1, col=1)
p4.setWindowTitle('Steering')
p4.setRange(QtCore.QRectF(0, -1, 100, 2))
p4.showGrid(True, True)
p5 = win.addPlot(title="Vehicle State",row=1, col=2)
p5.setWindowTitle('Vehicle State')
p5.setRange(QtCore.QRectF(0, 0, 100, 10))
p5.showGrid(True, True)
p6 = win.addPlot(title="Errors",row=1, col=3)
p6.setWindowTitle('Errors')
p6.setRange(QtCore.QRectF(0, 0, 100, 10))
p6.showGrid(True, True)
p7 = win.addPlot(title="Counter",row=0, col=4)
p8 = win.addPlot(title="Counter",row=1, col=4)
font=QtGui.QFont()
font.setPixelSize(300)
anchor = pg.TextItem()
anchor.setText("0")
anchor.setColor(QtGui.QColor(255, 255, 255))
anchor.setFont(font)
anchor1 = pg.TextItem()
anchor1.setText("0")
anchor1.setColor(QtGui.QColor(255, 255, 255))
anchor1.setFont(font)
p7.addItem(anchor)
p7.showGrid(False, False)
p7.hideAxis('bottom')
p7.hideAxis('left')
p8.addItem(anchor1)
p8.showGrid(False, False)
p8.hideAxis('bottom')
p8.hideAxis('left')
curve = p1.plot(pen='r')
curve2 = p2.plot(pen='b')
curve3 = p3.plot(pen='g')
curve4 = p4.plot(pen='y')
curve5 = p5.plot(pen='r')
curve6 = p6.plot(pen='b')
# Receive UDP packets transmitted by a broadcasting service
RECEIVE_IP = ''
RECEIVE_PORT = 2337
RECEIVE_ADDRESS = (RECEIVE_IP, RECEIVE_PORT)
recv_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
recv_socket.bind(RECEIVE_ADDRESS)
JOY_CODE = '=HBBBhHQQB'
ACK_CODE = '=HHBBHBBhBqB'
ptr = 0
lastTime = time()
fps = None
def update():
global recv_socket, fScale
global curve, data, data_throttle, data_brake, data_steering, ptr, p, lastTime, fps, data_state, data_error
recv_message, address = recv_socket.recvfrom(22)
message_id, ack_payload, ack_seq, vehicle_state, vehicle_speed, throttle, brake, steering, error, timestamp, checksum = struct.unpack(ACK_CODE, recv_message)
#data = throttle
data.append(ack_seq)
data = data[-100:]
data_throttle.append(throttle)
data_throttle = data_throttle[-100:]
data_brake.append(brake)
data_brake = data_brake[-100:]
data_steering.append(steering / 32768)
data_steering = data_steering[-100:]
vehicle_state = vehicle_state & 0x07
data_state.append(vehicle_state)
data_state = data_state[-100:]
data_error.append(error)
data_error = data_error[-100:]
curve.setData(data,_callSync='off')
curve2.setData(data_throttle,_callSync='off')
curve3.setData(data_brake,_callSync='off')
curve4.setData(data_steering,_callSync='off')
curve5.setData(data_state, _callSync='off')
curve6.setData(data_error, _callSync='off')
#Updating Text Value
anchor.setText(str(vehicle_state))
anchor1.setText(str(vehicle_state))
now = time()
dt = now - lastTime
lastTime = now
app.processEvents() ## force complete redraw for every plot
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
Below is my code my function receives data blocks from the server and puts them in a FIFO buffer after which two functions are called in parallel,
recvData() #to keep receiving data blocks from the server and put in the FIFO buffer
calculate_threshold() #to remove data blocks from the FIFO buffer and perform some calculation, give a real time display on the GUI, and write the result in the file
Code
import socket
import turtle
#import timeit
import queue
import multiprocessing
from tkinter import *
class GUI:
def __init__(self, master):
self.master = master
master.title("Collision Detection")
self.buff_data = queue.Queue()
self.p1 = multiprocessing.Process(target = self.recvData)
self.p1 = multiprocessing.Process(target=self.calculate_threshold)
self.input_label = Label(root, text = "Input all the gratings set straight wavelength values in nm")
self.input_label.grid(row = 0)
self.core_string = "Core "
self.entries = []
self.label_col_inc = 0
self.entry_col_inc = 1
self.core_range = range(1, 5)
for y in self.core_range:
self.core_text = self.core_string + str(y) + '_' + '25'
self.core_label = Label(root, text = self.core_text)
self.entry = Entry(root)
self.core_label.grid(row=1, column=self.label_col_inc, sticky=E)
self.entry.grid(row=1, column=self.entry_col_inc)
self.entries.append(self.entry)
self.label_col_inc += 2
self.entry_col_inc += 2
self.threshold_label = Label(root, text = "Threshold in nm")
self.entry_threshold = Entry(root)
self.threshold_label.grid(row = 2, sticky = E)
self.entry_threshold.grid(row = 2, column = 1)
self.light_label = Label(root, text = 'Status')
self.light_label.grid(row = 3, column = 3)
self.canvas = Canvas(root, width = 150, height = 50)
self.canvas.grid(row = 4, column = 3)
# Green light
self.green_light = turtle.RawTurtle(self.canvas)
self.green_light.shape('circle')
self.green_light.color('grey')
self.green_light.penup()
self.green_light.goto(0,0)
# Red light
self.red_light = turtle.RawTurtle(self.canvas)
self.red_light.shape('circle')
self.red_light.color('grey')
self.red_light.penup()
self.red_light.goto(40,0)
self.data_button = Button(root, text = "Get data above threshold", command = self.getData)
self.data_button.grid(row = 5, column = 0)
# function to receive TCP data blocks
def getData(self):
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
len_message = s.recv(4)
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = s.recv(bytes_length)
self.buff_data.put(recvd_data)
self.p1.start()
self.p2.start()
self.p1.join()
self.p2.join()
def recvData(self):
len_message = s.recv(4)
while len_message:
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = s.recv(bytes_length)
self.buff_data.put(recvd_data)
len_message = s.recv(4)
else:
print('out of loop')
s.close()
def calculate_threshold(self):
rmv_data = self.buff_data.get()
stringdata = rmv_data.decode('utf-8')
rep_str = stringdata.replace(",", ".")
splitstr = rep_str.split()
# received wavelength values
inc = 34
wav_threshold = []
for y in self.entries:
straight_wav = float(y.get())
wav = float(splitstr[inc])
wav_diff = wav - straight_wav
if wav_diff < 0:
wav_diff = wav_diff * (-1)
wav_threshold.append(wav_diff)
inc += 56
threshold = float(self.entry_threshold.get())
# writing into the file
data = []
inc1 = 0
col1 = 2
col2 = 6
data.insert(0, (str(splitstr[0])))
data.insert(1, (str(splitstr[1])))
for x in wav_threshold:
if (x > threshold):
self.red_light.color('red')
self.green_light.color('grey')
data.insert(col1, (str(splitstr[34 + inc1])))
data.insert(col2,(str(x)))
else:
self.red_light.color('grey')
self.green_light.color('green')
data.insert(col1,'-')
data.insert(col2,'-')
inc1 += 56
col1 += 1
col2 += 1
self.write_file(data)
# function to write into the file
def write_file(self,data):
with open("Output.txt", "a") as text_file:
text_file.write('\t'.join(data[0:]))
text_file.write('\n')
if __name__ == '__main__':
root = Tk()
gui = GUI(root)
root.mainloop()
But I get the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/PycharmProjects/GUI/GUI_v4.py", line 88, in getData
self.p1.start()
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 326, in _Popen
return Popen(process_obj)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_tkinter.tkapp' object
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
Can someone tell where exactly am I going wrong here?
The error is telling you that you can't use multiprocessing for an object that includes tkinter widgets. You're trying to use self.recvData in a separate process. That requires that self be pickled so that it can be sent to the other process. However, python can't do it because it contains tkinter widgets which cannot be pickled.
You will need to move the code which runs in another process to a separate class that does not contain any tkinter widgets.
Code changed after creating a new class:
import socket
import turtle
# import timeit
import queue
import multiprocessing
from tkinter import *
class GUI:
def __init__(self, master):
self.master = master
master.title("Collision Detection")
self.input_label = Label(root, text="Input all the gratings set straight wavelength values in nm")
self.input_label.grid(row=0)
self.core_string = "Core "
self.entries = []
self.label_col_inc = 0
self.entry_col_inc = 1
self.core_range = range(1, 5)
for y in self.core_range:
self.core_text = self.core_string + str(y) + '_' + '25'
self.core_label = Label(root, text=self.core_text)
self.entry = Entry(root)
self.core_label.grid(row=1, column=self.label_col_inc, sticky=E)
self.entry.grid(row=1, column=self.entry_col_inc)
self.entries.append(self.entry)
self.label_col_inc += 2
self.entry_col_inc += 2
self.threshold_label = Label(root, text="Threshold in nm")
self.entry_threshold = Entry(root)
self.threshold_label.grid(row=2, sticky=E)
self.entry_threshold.grid(row=2, column=1)
self.light_label = Label(root, text='Status')
self.light_label.grid(row=3, column=3)
self.canvas = Canvas(root, width=150, height=50)
self.canvas.grid(row=4, column=3)
# Green light
self.green_light = turtle.RawTurtle(self.canvas)
self.green_light.shape('circle')
self.green_light.color('grey')
self.green_light.penup()
self.green_light.goto(0, 0)
# Red light
self.red_light = turtle.RawTurtle(self.canvas)
self.red_light.shape('circle')
self.red_light.color('grey')
self.red_light.penup()
self.red_light.goto(40, 0)
self.data_button = Button(root, text="Get data above threshold", command=recv_data.getData)
self.data_button.grid(row=5, column=0)
class recv_data:
def __init__(self):
self.buff_data = queue.Queue()
self.p1 = multiprocessing.Process(target=self.recvData)
self.p1 = multiprocessing.Process(target=self.calculate_threshold)
self.host = '127.0.0.1'
self.port = 5002
self.s = socket.socket()
self.s.connect((self.host, self.port))
# function to receive TCP data blocks
def getData(self):
len_message = self.s.recv(4)
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = self.s.recv(bytes_length)
self.buff_data.put(recvd_data)
self.p1.start()
self.p2.start()
self.p1.join()
self.p2.join()
def recvData(self):
len_message = self.s.recv(4)
while len_message:
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = self.s.recv(bytes_length)
self.buff_data.put(recvd_data)
len_message = self.s.recv(4)
else:
print('out of loop')
self.s.close()
def calculate_threshold(self):
rmv_data = self.buff_data.get()
stringdata = rmv_data.decode('utf-8')
rep_str = stringdata.replace(",", ".")
splitstr = rep_str.split()
# received wavelength values
inc = 34
wav_threshold = []
for y in gui.entries:
straight_wav = float(y.get())
wav = float(splitstr[inc])
wav_diff = wav - straight_wav
if wav_diff < 0:
wav_diff = wav_diff * (-1)
wav_threshold.append(wav_diff)
inc += 56
threshold = float(gui.entry_threshold.get())
# writing into the file
data = []
inc1 = 0
col1 = 2
col2 = 6
data.insert(0, (str(splitstr[0])))
data.insert(1, (str(splitstr[1])))
for x in wav_threshold:
if (x > threshold):
gui.red_light.color('red')
gui.green_light.color('grey')
data.insert(col1, (str(splitstr[34 + inc1])))
data.insert(col2, (str(x)))
else:
gui.red_light.color('grey')
gui.green_light.color('green')
data.insert(col1, '-')
data.insert(col2, '-')
inc1 += 56
col1 += 1
col2 += 1
self.write_file(data)
# function to write into the file
def write_file(self, data):
with open("Output.txt", "a") as text_file:
text_file.write('\t'.join(data[0:]))
text_file.write('\n')
if __name__ == '__main__':
root = Tk()
gui1 = GUI(root)
rec_data = recv_data()
root.mainloop()
Error that I get:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
TypeError: getData() missing 1 required positional argument: 'self'
Lately I have been working on my python chat project, the server works well but when I use the threading model to run the gui of the client and the select I have a problem with it.
I am able to send data to the server and the server returns the data to the clients but the clients can't print the data.
This is the code of the client :
import socket
import select
from Tkinter import *
import thread
class client(object):
def __init__(self):
self.client_socket = socket.socket()
self.messages =[]
def connect(self):
self.client_socket.connect(('127.0.0.1', 1234))
def getgui(self, window):
self.root = window
def run(self):
while True:
self.rlist, self.wlist, self.xlist = select.select([self.client_socket], [self.client_socket], [])
for current_socket in self.rlist:
data = current_socket.recv(1024)
self.root.print_on_list(data)
def send_to_server(self, word):
self.client_socket.send(word)
class rootgui():
def __init__(self,client_socket):
self.client_socket = client_socket
self.root = Tk()
self.root.geometry('600x700')
self.root.minsize(600, 700)
self.root.maxsize(600, 700)
self.root.title('chat')
self.frame = Frame(self.root)
self.frame.pack()
self.scrollbar = Scrollbar(self.frame)
self.scrollbar.pack(side = RIGHT, fill = Y)
self.chatlist = Listbox(self.frame, yscrollcommand = self.scrollbar.set, width = 80, height = 25 )
self.chatlist.pack(side = LEFT)
self.leftframe = Frame(self.root)
self.leftframe.pack(side = LEFT)
self.send_button = Button(self.leftframe, text = 'send', bg = 'green', padx = 60, pady = 70, command = self.send)
self.send_button.pack()
self.rightframe = Frame(self.root)
self.rightframe.pack(side = RIGHT)
self.text = StringVar()
self.input_box = Entry(self.rightframe, width =55, textvariable = self.text )
self.input_box.pack()
self.scrollbar.config(command = self.chatlist.yview)
def mainloop(self):
self.root.mainloop()
def send(self):
t = self.text.get()
self.client_socket.send_to_server(t)
return
def print_on_list(self, data):
self.chatlist.insert(END, data+'\r\n')
def main():
client_socket = client()
client_socket.connect()
window = rootgui(client_socket)
client_socket.getgui(window)
thread.start_new_thread(window.mainloop())
thread.start_new_thread(client_socket.run())
if __name__ == '__main__':
main()
This is the code of the server:
import socket
import select
class server(object):
''' init function '''
def __init__(self):
self.server_socket = socket.socket()
self.open_client_sockets = []
'''this function send a message to all of the connected clients'''
def send_messages(self, message):
for client_socket in self.open_client_sockets:
client_socket.send(message)
''' this function get a port , it bind the server socket and set the listen to 5 sockets '''
def connection(self):
self.server_socket.bind(('0.0.0.0', 1234))
self.server_socket.listen(5)
''' this function use the select library and read / write from / to the client socket '''
def run(self):
while True:
self.rlist, self.wlist, self.xlist = select.select([self.server_socket]+self.open_client_sockets, self.open_client_sockets, [])
for current_socket in self.rlist:
if current_socket is self.server_socket:
(new_socket, address) = self.server_socket.accept()
self.open_client_sockets.append(new_socket)
print 'new member : ' + str(address)
else:
try:
data = current_socket.recv(1024)
self.send_messages(data)
break
except socket.error:
self.open_client_sockets.remove(current_socket)
print 'Connection with client closed.'
if __name__ == '__main__':
server_socket = server()
server_socket.connection()
server_socket.run()