【问题标题】:Matplotlib live data animation runs out of memoryMatplotlib 实时数据动画内存不足
【发布时间】:2022-01-04 14:24:39
【问题描述】:

我正在使用 Raspberry Pi 从串行中绘制实时数据,但最终内存不足。我不确定是否/如何关闭该图,但仍然有实时数据显示。

是否可以为每个动画创建和关闭一个新人物?

我现在的代码:

import serial
import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('TkAgg') #comment out for debugging
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import gc

# Create figure for plotting
fig = plt.figure()

xs = []
ysAC = []
ysDC = []

ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
ser.flush()

# This function is called periodically from FuncAnimation
def animate(i, xs, ysAC, ysDC):

  values = getValues()

  wAC = values[1]
  wDC = values[2]
 
  # Add x and y to lists
  xs.append(i)
  ysAC.append(wAC)
  ysDC.append(wDC)

  # Limit x and y lists to 10 items
  xs = ['T-9','T-8','T-7','T-6','T-5','T-4','T-3','T-2','T-1','Now'] 
  ysDC = ysDC[-10:]
  ysAC = ysAC[-10:]

  # Draw x and y lists
  axRT1.clear()   
    
  if len(ysDC) == 10:
    lineAC, = axRT1.plot(xs, ysAC, 'b:', label='Mains', linewidth = 4)
    lineDC, = axRT1.plot(xs, ysDC, 'g--', label='Solar', linewidth = 4)
    
  gc.collect()
  #fig.clf()
  #plt.close()

def getValues():
  
  if ser.in_waiting > 0:
    line = ser.readline().decode('utf-8').rstrip()   
    return list(line.split(","))  

# Set up plot to call animate() function periodically
ani = animation.FuncAnimation(fig, animate, fargs=(xs, ysAC, ysDC), interval=1000, blit=False)
plt.get_current_fig_manager().full_screen_toggle()
plt.ioff()
plt.show()
plt.draw()

【问题讨论】:

  • 不要每次都作图。更改现有绘图的 x 和 y 数据。
  • @JodyKlymak 谢谢。我不明白为什么 set_data 返回 AttributeError: 'NoneType' object has no attribute 'update'

标签: python matplotlib animation ram


【解决方案1】:

清除下面标记的地块的粗略方法为我修复了它:

import time
import serial
import datetime as dt
import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('TkAgg') #comment out for debugging
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.animation as animation
from decimal import Decimal
import pandas as pd
import numpy as np
import os.path as path
import re
import gc
import os

count = 0

# Create figure for plotting
fig = plt.figure()
fig.patch.set_facecolor('whitesmoke')
hFont = {'fontname':'sans-serif', 'weight':'bold', 'size':'12'}

xs = ['T-9','T-8','T-7','T-6','T-5','T-4','T-3','T-2','T-1','Now'] 
ysTemp = []
ysAC = []
ysDC = []

axRT1 = fig.add_subplot(2, 2, 1)
axRT2 = axRT1.twinx()  # instantiate a second axes that shares the same x-axis
#Draw x and y lists
axRT1.clear()   
axRT2.clear()
axRT1.set_ylim([0, 4])
axRT2.set_ylim([10, 70])

axRT1.set_ylabel('Power Consumption kW', **hFont)
axRT2.set_ylabel('Temperature C', **hFont)
axRT1.set_xlabel('Seconds', **hFont)
axRT1.set_title('Power Consumption and Temperature - Real Time', **hFont)
lineTemp, = axRT2.plot([], [], 'r', label='Temp', linewidth = 4)
lineAC, = axRT1.plot([], [], 'b:', label='Mains', linewidth = 4)
lineDC, = axRT1.plot([], [], 'g--', label='Solar', linewidth = 4)
fig.legend([lineAC, lineDC,lineTemp], ['Mains', 'Solar', 'Temp'], fontsize=20)

ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
ser.flush()

# This function is called periodically from FuncAnimation
def animate(i, xs, ysTemp, ysAC, ysDC):

  values = getValues()

  if values != 0:
    temp_c = Decimal(re.search(r'\d+',values[3]).group())
    if temp_c < 0: temp_c = 0
    wAC = round(Decimal(re.search(r'\d+', values[1]).group())/1000, 2)
    if wAC < 0.35: wAC = 0
    aDC = float(re.search(r'\d+', values[2]).group()) #remove characters
    vDC = float(re.search(r'\d+', values[4][:5]).group()) #remove characters
    wDC = aDC * vDC
    wDC = round(abs(Decimal(wDC))/1000, 2)


    # Add x and y to lists
    ysTemp.append(temp_c)
    ysAC.append(wAC)
    ysDC.append(wDC)

    # Limit x and y lists to 10 items
    ysTemp = ysTemp[-10:]
    ysDC = ysDC[-10:]
    ysAC = ysAC[-10:]

    if len(ysTemp) == 10:
      axRT2.lines = [] #This crude way of clearing the plots worked
      axRT1.lines =[] #This crude way of clearing the plots worked
      lineTemp, = axRT2.plot(xs, ysTemp, 'r', label='Temp', linewidth = 4)
      lineAC, = axRT1.plot(xs, ysAC, 'b:', label='Mains', linewidth = 4)
      lineDC, = axRT1.plot(xs, ysDC, 'g--', label='Solar', linewidth = 4)



def getValues():

  measureList = 0

  if ser.in_waiting > 0:
    line = ser.readline().decode('utf-8').rstrip()
    print(line)

    if line.count(',') == 4:
      measureList = list(line.split(","))  

  return measureList

# Set up plot to call animate() function periodically
ani = animation.FuncAnimation(fig, animate, fargs=(xs, ysTemp, ysAC, ysDC), interval=1000, blit=False)
plt.get_current_fig_manager().full_screen_toggle()
plt.ioff()
plt.show()
plt.draw()

【讨论】:

    猜你喜欢
    • 2021-07-18
    • 2016-08-06
    • 2020-04-19
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    相关资源
    最近更新 更多