目录
最近有个需求,将后台实时生成的数据,用曲线可视化表达出来,并且动态更新数据。查找相关资料,matplotlib可以满足该需求。
一:目标
生成的数据是存在csv文件里,程序要不断的去读取csv文件里的数据,以曲线的形式动态的显示出来。有两个csv文件,所以需要显示两张图,另外每张图里有多条曲线。选用python3的第三方库matplotlib来完成该项工作。
二:matplotlib简介
Matplotlib是一个Python的2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。通过Matplotlib,开发者可以仅需要几行代码,便可以生成绘图。一般可绘制折线图、散点图、柱状图、饼图、直方图、子图等等。
学习matplotlib编程,最直接的就是去官网上找例子,官网上的例子非常丰富,几乎涵盖了常用的图形,看看给出的daemon程序基本就可以上手。给出官网链接:https://matplotlib.org/stable/gallery/index.html
三:功能实现
python用matplotlib编程,网上给出的资料大多是面向过程的编程,类似于脚本一样,这样的程序如果就自己写着玩的,可以快速的实现,但是这种程序一是不容易维护,二是不容易扩展。matplotlib有面向对象的编程方法。该次实践同样会利用面向对象的编程思想来完成本项工作。下面以子功能为单位来介绍
1,实时读取csv文件
本次会实时读取两个文件,为了不影响主程序运行,单独开辟了两个线程来实时更新数据
def threadHandleCsvData(self):
dataThread1 = threading.Thread(target=self.fun1)
dataThread2 = threading.Thread(target=self.fun2)
dataThread1.start()
dataThread2.start()
线程函数fun来读取csv文件,并且进行数据处理,具体数据处理的代码由各位根据自己要展示的数据进行处理。本次读取csv文件用的库就是csv库,为了方便对csv读取的对象进行遍历,转化成list列表
dataList= list(csv.reader(open(file,'r')))
2,matplotlib面向对象的编程
本次功能需要展示两张图,每张图有多个曲线
class daemonDynamicClass():
def __init__(self,fileVolume,filePps):
self.color = ['blue','cyan','green','red','darkorange','magenta','olive','black']
self.TreadList = ['Thread0','Thread1','Thread2','Thread3','Thread4','Thread5','Thread6','Thread7']
self.fig = plt.figure("---title---")
self.fig.subplots_adjust(top=0.92,hspace=0.25,bottom = 0.08) # 调整边距和子图的间距
self.ax1 = self.fig.add_subplot(211)
self.ax1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))#设置时间标签显示格式
self.ax1.set_ylabel('y1')
self.ax1.set_xlabel('x1')
self.ax1.grid(ls='--')
self.ax2 = self.fig.add_subplot(212)
self.ax2.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))#设置时间标签显示格式
self.ax2.set_ylabel('y2')
self.ax2.set_xlabel('x2')
self.ax2.grid(ls='--')
mng = plt.get_current_fig_manager()
mng.window.state("zoomed")
对其中的有些必要函数做出详细解释
self.ax1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))#设置时间标签显示格式
本次x轴的数据就是时间,如果不设置成时间格式让matplotlib生成的图来识别时间,则x轴的数据会随着时间的积累,显示越来越密集,最后x轴显示的密密麻麻,都叠加到一起了,这不是我们想要的,该行代码就是将x轴设置成时间标签显示,当两格的时间标注碰到一起的时候会默认拉长时间间隔,这样会显示的非常清晰。
self.ax1 = self.fig.add_subplot(211)
*argsint, (int, int, index), or
SubplotSpec
, default: (1, 1, 1)The position of the subplot described by one of
- Three integers (nrows, ncols, index). The subplot will take the index position on a grid with nrows rows and ncols columns. index starts at 1 in the upper left corner and increases to the right. index can also be a two-tuple specifying the (first, last) indices (1-based, and including last) of the subplot, e.g.,
fig.add_subplot(3, 1, (1, 2))
makes a subplot that spans the upper 2/3 of the figure.- A 3-digit integer. The digits are interpreted as if given separately as three single-digit integers, i.e.
fig.add_subplot(235)
is the same asfig.add_subplot(2, 3, 5)
. Note that this can only be used if there are no more than 9 subplots.- A
SubplotSpec
.In rare circumstances,
add_subplot
may be called with a single argument, a subplot Axes instance already created in the present figure but not in the figure's list of Axes.
211实际上是三个参数2,1,1,该行代码也可以写成add_subplot(2,1,1),211的意思就是fig画布对象添加两行一列的图,选择第一行的区域。
self.ax1.grid(ls='--')
ax1.grid(ls='--')作用是曲线图里有网格线,为了好看,纯粹个人喜好。
mng = plt.get_current_fig_manager()
mng.window.state("zoomed")
以上两行代码的作用是运行出来的图默认全屏显示,不然是以默认的小窗口显示,由于本次显示的数据比较多,如果不设置全屏显示,线都挤一起去了,很难看,所以默认设置的是全屏显示。
3,动态显示曲线
如何动态显示曲线,可以照着csdn上的很多资料,用for或者while纯手撸来达到曲线动态更新的效果,matplotlib