Python Matplotlib在动画刷新后连接数据的结尾
我遇到了一个和帖子完全一样的问题,但有点让人沮丧 我使用matplotlib从另一个应用程序提供数据的文件中读取数据。由于某些原因,只有在动画(Python Matplotlib在动画刷新后连接数据的结尾,python,python-2.7,matplotlib,Python,Python 2.7,Matplotlib,我遇到了一个和帖子完全一样的问题,但有点让人沮丧 我使用matplotlib从另一个应用程序提供数据的文件中读取数据。由于某些原因,只有在动画(animation.FuncAnimation)完成第一次刷新后,数据的两端才会连接。以下是一些图片: 这是在刷新之前: 这是在刷新之后: 你知道为什么会这样吗?这是我的密码: import json import itertools import dateutil.parser import matplotlib.pyplot as plt im
animation.FuncAnimation
)完成第一次刷新后,数据的两端才会连接。以下是一些图片:
这是在刷新之前:
这是在刷新之后:
你知道为什么会这样吗?这是我的密码:
import json
import itertools
import dateutil.parser
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
import scipy.signal as sig
import numpy as np
import pylab as plt
sensors = {}
data = []
lastLineReadNum = 0
class Sensor:
def __init__(self, name, points = 0, lastReading = 0):
self.points = points
self.lastReading = lastReading
self.name = name
self.x = []
self.y = []
class ScanResult:
def __init__(self, name, id, rssi, macs, time):
self.name = name
self.id = id
self.rssi = rssi
self.macs = macs
# Is not an integer, but a datetime.datetime
self.time = time
def readJSONFile(filepath):
with open(filepath, "r") as read_file:
global lastLineReadNum
# Load json results into an object that holds important info
for line in itertools.islice(read_file, lastLineReadNum, None):
temp = json.loads(line)
# Only reads the most recent points...
data.append(ScanResult(name = temp["dev_id"],
id = temp["hardware_serial"],
rssi = temp["payload_fields"]["rssis"],
macs = temp["payload_fields"]["macs"],
time = dateutil.parser.parse(temp["metadata"]["time"])))
lastLineReadNum += 1
return data
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
def smooth(y, box_pts):
box = np.ones(box_pts)/box_pts
y_smooth = np.convolve(y, box, mode='same')
return y_smooth
def determineClosestSensor():
global sensors
#sensors.append(Sensor(time = xs3, rssi = ys3))
def determineXAxisTime(scanresult):
return ((scanresult.time.hour * 3600) + (scanresult.time.minute * 60) + (scanresult.time.second)) / 1000.0
def animate(i):
data = readJSONFile(filepath = "C:/python_testing/rssi_logging_json.json")
for scan in data:
sensor = sensors.get(scan.name)
# First time seeing the sensor
if(sensor == None):
sensors[scan.name] = Sensor(scan.name)
sensor = sensors.get(scan.name)
sensor.name = scan.name
sensor.x.append(determineXAxisTime(scan))
sensor.y.append(scan.rssi)
else:
sensor.x.append(determineXAxisTime(scan))
sensor.y.append(scan.rssi)
ax1.clear()
#basic smoothing using nearby averages
#y_smooth3 = smooth(np.ndarray.flatten(np.asarray(sensors.get("sentrius_sensor_3").y)), 1)
for graphItem in sensors.itervalues():
smoothed = smooth(np.ndarray.flatten(np.asarray(graphItem.y)), 1)
ax1.plot(graphItem.x, smoothed, label = graphItem.name, linewidth = 2.0)
ax1.legend()
determineClosestSensor()
fig.suptitle("Live RSSI Graph from Sentrius Sensors", fontsize = 14)
def main():
ani = animation.FuncAnimation(fig, animate, interval = 15000)
plt.show()
if __name__ == "__main__":
main()
据我所知,您正在通过附加到现有数据集来重新生成每个动画步骤中的数据,但这意味着第一步中的最后一个
x
点之后是第二步中的第一个x
点,从而导致绘图中的回放。这显示为连接最后一个数据点和第一个数据点的线;其余数据保持不变
动画的相关部分:
def animate(i):
data = readJSONFile(filepath = "C:/python_testing/rssi_logging_json.json")
for scan in data:
sensor = sensors.get(scan.name)
# First time seeing the sensor
if(sensor is None): # always check for None with `is`!
... # stuff here
else:
sensor.x.append(determineXAxisTime(scan)) # always append!
sensor.y.append(scan.rssi) # always append!
... # rest of the stuff here
因此,在每个动画步骤中
1.加载相同的JSON文件
2.将相同的数据附加到由sensors.get(scan.name)
3.在不使用i
的情况下打印内容
首先,你的动画
应该自然地使用索引i
:你正在尝试做一些与步骤i
有关的事情。我看不到I
在任何地方被使用
其次,您的动画
应该尽可能轻,以便获得平滑的动画。打印前加载数据一次,仅在动画中处理图形差异。这将涉及将数据作为i
的函数进行切片或操作
当然,如果文件确实在一步一步地更改,并且这是动画中的实际动态(即,i
是一个从未使用过的虚拟变量),则只需将每个步骤中的所有打印数据初始化为零即可。从头开始。然后,您将不再看到数据中与这些人工跳跃对应的线条。但是,同样,如果您想要一个轻量级的动画
,您应该考虑操作现有绘图的基础数据,而不是一直重复所有内容(特别是因为调用ax1.plot
将保留画布上的早期点,这不是您通常希望在动画中使用的).次要说明:库的名称为matplotlib。