【发布时间】:2021-10-19 11:49:01
【问题描述】:
我在使用 Python 中的多个线程时遇到问题。让我给出上下文,我正在尝试从示波器中读取值并实时制作直方图。但问题是实时绘图使我的测量速度非常慢。
所以我想在一个线程中读取示波器中的值,然后在另一个线程中绘制直方图 - 这应该可以解决缓慢问题。由于我是 python 的初学者,我遇到了很多错误。
这是我写的代码:
import time
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import PercentFormatter
from numpy.core.shape_base import block
import pyvisa
import os
from matplotlib.pyplot import figure, step
from scipy.signal import find_peaks
import queue
import threading
def acquisition(queue, name):
rm = pyvisa.ResourceManager()
rta = rm.open_resource('TCPIP::192.168.100.101::INSTR')
path='Desktop/Laboratorio/Programacion-
Automatizacion/Pyvisa/Output/'
rta.write("MEASurement1:TIMeout:AUTO")
valuep = []
aux = 0
#Comprobamos que no existen ya esos ficheros
if os.path.isfile(path + name + '.txt'):
os.remove(path + name + '.txt')
if os.path.isfile(path + name + '.png'):
os.remove(path + name + '.png')
start_time = time.time()
aux
entries=1000
gain=0
completed = 0
while len(valuep) < entries:
if rta.query("*OPC?"):
p1=float(rta.query("CURSor1:Y1Position?"))
if rta.query("*OPC?"):
p2=float(rta.query("CURSor1:Y2Position?"))
r=(p1-p2)
valuep.append(r)
a = np.array(valuep)
completed = len(valuep)/entries*100
print(str(completed) + ' %\n')
hist, bin_edges = np.histogram(a, 300)
bin_edges = bin_edges[1:]
peaks, _ = find_peaks(hist, distance=10, prominence=10)
sumDelta = 0
if len(peaks) >= 2:
sumDelta = 0
for i in range(len(peaks)-1):
deltaV=bin_edges[peaks[i+1]]-bin_edges[peaks[i]]
sumDelta += deltaV
gain=(sumDelta/(len(peaks)-1))/(50*1.602e-19)
if completed == 10 or completed == 20 or completed == 30 or
completed == 40 or completed == 50 or completed == 60 or
completed == 70 or completed == 80 or completed == 90 or
completed == 100:
auxLen = np.arange(0 , len(valuep) , 1)
with open(path + name + '.txt', 'w') as f:
f.write(str(gain) + ' | ' + str(round((time.time() -
start_time)/60, 3)) + '\n')
for i in auxLen:
f.write(str(valuep[i]))
f.write('\n')
message = a
queue.put(message)
rta.close()
def histogram(queue, name):
while True:
message = queue.get()
plt.cla()
# plt.xlabel("Vs | %=" + str(round(len(valuep)/entries*100, 3)) + " | Time: " + str(round((time.time() - start_time)/60, 3)) + " min")
plt.ylabel("Bins")
plt.yscale('log')
hist, bin_edges = np.histogram(message, 300)
bin_edges = bin_edges[1:]
plt.plot(bin_edges, hist)
# plt.plot(bin_edges[peaks], hist[peaks], "x")
plt.show()
plt.tight_layout()
if __name__ == "__main__":
print('Input code name: ')
name = input()
q = queue.Queue()
acquire = threading.Thread(target=acquisition, args=(q, name,))
hist = threading.Thread(target=histogram, args=(q, name,))
acquire.start()
hist.start()
acquire.join()
hist.join()
q.join()
plt.plot()
函数acquire从示波器中读取值并以numpy数组的形式返回到队列中。
错误是:
UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
非常感谢您的帮助和任何 cmets,我应该如何进行。提前致谢。
这是我一开始的代码:
#librerias
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import PercentFormatter
import pyvisa
import time
import os
from itertools import count
from matplotlib.animation import FuncAnimation
from matplotlib.pyplot import figure, step
from scipy.signal import find_peaks
#Abrir sesion VISA
rm = pyvisa.ResourceManager()
rta = rm.open_resource('TCPIP::192.168.100.101::INSTR')
print('Input code name: ')
name=input()
path='Desktop/Laboratorio/Programacion-Automatizacion/Pyvisa/Output/'
rta.write("MEASurement1:TIMeout:AUTO")
rta.write("SYSTem:COMMunicate:INTerface:ETHernet:TRANsfer FD100")
rta.write("FORM BIN") # // Set BIN data format
valuep = []
aux = 0
#Comprobamos que no existen ya esos ficheros
if os.path.isfile(path + name + '.txt'):
os.remove(path + name + '.txt')
if os.path.isfile(path + name + '.png'):
os.remove(path + name + '.png')
start_time = time.time()
def animate(i):
global aux
entries=1000
gain=0
if rta.query("*OPC?"):
p1=float(rta.query("CURSor1:Y1Position?"))
if rta.query("*OPC?"):
p2=float(rta.query("CURSor1:Y2Position?"))
r=(p1-p2)
valuep.append(r)
a = np.array(valuep)
plt.cla()
plt.xlabel("Vs | %=" + str(round(len(valuep)/entries*100, 3)) + " | Time: " + str(round((time.time() - start_time)/60, 3)) + " min")
plt.ylabel("Bins")
plt.yscale('log')
hist, bin_edges = np.histogram(a, 300)
bin_edges = bin_edges[1:]
plt.plot(bin_edges, hist)
peaks, _ = find_peaks(hist, distance=10, prominence=10)
sumDelta = 0
if len(peaks) >= 2:
sumDelta = 0
for i in range(len(peaks)-1):
deltaV=bin_edges[peaks[i+1]]-bin_edges[peaks[i]]
sumDelta += deltaV
gain=(sumDelta/(len(peaks)-1))/(50*1.602e-19)
#print(gain)
plt.plot(bin_edges[peaks], hist[peaks], "x")
plt.show()
plt.tight_layout()
#Escritura fichero CSV
if len(valuep) == entries:
auxLen = np.arange(0 , len(valuep) , 1)
with open(path + name + '.txt', 'w') as f:
f.write(str(gain) +'\n')
for i in auxLen:
f.write(str(valuep[i]))
f.write('\n')
plt.savefig(path + name + '.png')
ani = FuncAnimation(plt.gcf(), animate, interval=0.013)
plt.tight_layout()
plt.show()
rta.close()
这段代码就像我想要的那样工作,但是非常慢,我说使用 aniFunction 进行绘图需要 96 分钟来获取 15000 次,而没有 anifunc 需要 26 分钟来获取 30000 次,这就是我尝试使用线程的原因。
【问题讨论】:
-
明天我会做一个“def获取”的例子发送给朋友,在没有范围的情况下进行复制,然后我将使用这段代码进行编辑。
-
UserWarning 实际上并不是一个错误,它表示它可能会失败。但是您面临的问题是什么?剧情正在发生?
-
@kris,你好 Kris,剧情正在实现,但不是实时更新,你说这个警告不是一个重要问题吗?你知道我如何在这里使用aniFunction吗?非常感谢您编辑我的英语和评论。
-
你能发布完整的代码吗?我不清楚您是否需要最后加入所有线程并进行绘图。 IMO,您还应该考虑多进程而不是多线程的可能性,因为它对性能改进的希望不大
-
@Kris 我可以上传我的第一个运行缓慢的代码,以及我现在拥有的代码吗?还是很多?
标签: python python-3.x