用Python读取.log文件内容并打印图像,鼠标点击图像点可以打印对应坐标

最近需要从.log文件中读取大量数据进行可视化,处理读取的时间戳和鼠标点击事件碰到一些坑,特此记录一下。

本文代码基于Ubuntu的pycharm进行开发,如遇问题多多交流。

本文处理的.log文件内容形式

09:46:26.048 value1: 100, value2: 1.1
09:46:26.055 value1: 200, value2: 2.2
09:46:26.067 value1: 150, value2: 3.6
09:46:26.075 value1: 300, value2: 5.8
09:46:26.088 value1: 500, value2: 4.7

读取.log文件内容并进行关键词提取

from datetime import datetime

value_t = []
time_stp = []

with open('ap_ctrl_2025-03-12_26.log', 'r') as file: #'r'代表以只读模式打开文件
    for line in file:
        line = line.strip() # 去除两端空白符
        if not line.startswith('#'): # 忽略注释行
            parts = line.split() # 每行根据空格分割字段
            if len(parts) > 2: # 根据实际字段数调整关键字索引
                # 根据关键字查找对应的值
                if 'value1:' in parts:
                    try:
                        key_word = 'value1:'
                        # 根据关键字查找其在parts中的下标,把下标的下一位根据逗号分割后,获得对应值
                        value_t.append(float(parts[parts.index(keyword) + 1].split(',')[0]))
                        # parts第一个元素是时间戳,需要使用datetime.strptime将字符串转换为时间格式,涉及库datetime
                        time_stp.append(datetime.strptime(parts[0], '%H:%M:%S.%f'))
                    except ValueError:
                        pass # 如果数据格式错误,则跳过此行

以第一行为例,经过line.split()按空格分割字段后,parts的内容应该是下面这样

parts = ["09:46:26.048", "value1:", "100,", "value2:", "1.1"]

而查找完整个.log文件后,value和time_stp的内容应该是这样

value_t = [100, 200, 150, 300, 500]
time_stp = [datetime.datetime(1900, 1, 1, 9, 46, 26, 048000),
            datetime.datetime(1900, 1, 1, 9, 46, 26, 055000),
            datetime.datetime(1900, 1, 1, 9, 46, 26, 067000),
            datetime.datetime(1900, 1, 1, 9, 46, 26, 075000),
            datetime.datetime(1900, 1, 1, 9, 46, 26, 088000)]

打印图像

把上面的数据用matplotlib.pyplot库打印成图像

需要注意的是,Windows和Ubuntu下用scatter打印散点图的操作有点区别,如果x轴打印的是上面的datetime类型,那么Ubuntu里得多加一句限制x轴打印范围的语句,不然打出来的图像里x轴的时间范围会很大,Windows里则不需要,打印出来会自适应数据范围,不知道是不是我电脑处理的个例。

其他的就是常规打印操作了,这里用plot直接打印折线图了,鼠标点击操作语句如果到此为止不需要的话就屏蔽叭

import matplotlib.pyplot as plt


fig = plt.figure(figsize=(15,5))
cid = fig.canvas.mpl_connect('button_press_event', mouse_event) # 鼠标事件相关
plt.plot(time_stp, value_t, marker='.', markersize=5)
plt.title('Time-Value')
plt.xlabel('Time')
plt.ylabel('Value')
plt.grid(True)

在Ubuntu中用scatter打印散点图时,如果x轴时间打出来不对劲,可以试试这么处理

from datetime import timedelta

fig = plt.figure(figsize=(15,5))
plt.scatter(time_stp, value_t, marker='o', s=5.)
# 限制x轴范围为第一个时间前5秒和最后一个时间后5秒,下标[-1]是从序列尾部逆序进行查找
plt.xlim(time_stp[0] - timedelta(seconds=5.), time_stp[-1] + timedelta(seconds=5.))
plt.title('Time-Value')
plt.xlabel('Time')
plt.ylabel('Value')
plt.grid(True)

鼠标点击图像上的点,在终端显示对应坐标值

操作分为这几步:

  1. 检测鼠标点击
  2. 根据点击的坐标查找距离最近的打印点
  3. 在图像上显示所选的点,并在终端打印坐标值

处理鼠标点击处的坐标时,总是转换不对时间,直接打印的值也很奇怪,后来发现需要用datas库的num2date进行转换,转来转去~转来转去~

import matplotlib.dates as mdates

# 定义鼠标点击事件,调用此函数的语句在上一节
def mouse_event(event):
    # 判断点击是否在坐标系内
    if not event.inaxes:
        return
    # 获取鼠标点击处的坐标信息
    x_click, y_click = event.xdata, event.ydata
    # 将x轴的坐标转换为时间,便于后面计算时间差,[:-3]裁剪掉末尾三位数,此处是为了仅保留小数点后3位
    t_click = mdates.num2date(x_click).strftime("%H:%M:%S.%f")[:-3]
    # 将上一句中被strftime转换为字符串的时间转换回datetime类型
    time_click = datetime.strptime(t_click, '%H:%M:%S.%f')
    # 计算每个打印点与点击处的距离,其中时间差为timedelta类型,从timedelta类型中得到秒与毫秒计算时间差
    dists = [((time_click - x_time).seconds + (time_click - x_time).microseconds*1e-6)**2 + (y - y_click)**2 for x_time, y in zip(time_stp, value_t)]
    dist_idx = dists.index(min(dists))
    # 如果距离过大,则需要避免误检
    if min(dists) > 5.0:
        print('Too far from plot points!')
        return
    closet_time = time_stp[dist_idx]
    print(f'time: {closet_time.strftime("%H:%M:%S.%f")[:-3]}, value_t: {value_t[time_idx]}') #使用[:-3]截掉最后的3位数
    print(f'click point time: {mdates.num2date(x_click).strftime("%H:%M:%S.%f")[:-3]}, value_t: {y_click}')
    plt.plot(closet_time, value_t[time_idx], 'o', color='red')
    plt.draw()

总的代码由上面部分组成,各部分集合起来的时候,把引入的库放一起就行,然后注意下定义的函数的位置。文中为了方便展示各部分所需的库,所以把库和部分代码放到一起了。

权当留个笔记给自己翻,也希望能帮到有需要的人叭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值