【问题标题】:Plotting inside a thread and update it (python)在线程内绘图并更新它(python)
【发布时间】: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


【解决方案1】:

好的,我已经解决了。我用过:

warnings.filterwarnings("忽略")

用于警告和:

ani = FuncAnimation(plt.gcf(), animate, interval=0.013)

使动画像以前一样。 现在我有一个检查队列是否为空的问题,如果我使用:

如果不是 queue.empty():

不工作,如果我不使用它,程序就会停止。 如果你愿意,我可以发布代码。谢谢大家。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多