我正面临一个在Python中使用多线程的问题。让我介绍一下背景,我正试图从示波器中读取数值,并实时绘制直方图。但问题是实时绘图使我的测量变得非常慢。
所以我想在一个线程中读取示波器的值,然后在另一个线程中绘制柱状图--这应该可以解决速度慢的问题。因为我是Python的初学者,我遇到了很多错误。
This is my code I wrote:
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()
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数组的形式返回到队列中。
The error is:
UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
我真的很感谢你的帮助和任何意见,我应该如何进行。请提前感谢。
这是我起初的代码。
#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绘图,15000次采集需要96分钟,而不用anifunc,30000次采集需要26分钟,这就是为什么我尝试用线程。