python_读取txt文件绘制指定数量的曲线V_保存图片

接上一篇文章,由于txt文件的内容太大,前端展示图片比较缓慢,优化后,前端不展示图片,仅仅保存指定分辨率大小的图片,不显示Y轴刻度等;

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from tkinter import *
from tkinter import filedialog
import os
import time
import re
from datetime import datetime
from pylab import mpl
import matplotlib

# matplotlib.use('TkAgg') # 解决serWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figur异常
matplotlib.use('agg')  # 前端不展示所绘制的图片
import matplotlib.pyplot as plt

mpl.rcParams["font.sans-serif"] = ["SimHei"]  # 设置显示中文字体
mpl.rcParams["axes.unicode_minus"] = False  # 设置正常显示符号

"""
out_los_GDHZ.txt文件内容
2024/03/05 05:50:01  sys:  1,prn:  8, f :  0, rr :  22776258.520521, cdts :  9499.326017, dtrpr :  0.000000, ionxr :  16.994414, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  8, f :  0, rr :  22776258.520521, cdts :  9499.326017, dtrpr :  0.000000, ionxr :  16.994414, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  8, f :  1, rr :  22776258.520521, cdts :  9499.326017, dtrpr :  0.000000, ionxr :  30.475578, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  8, f :  1, rr :  22776258.520521, cdts :  9499.326017, dtrpr :  0.000000, ionxr :  30.475578, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  14, f :  0, rr :  23343648.060891, cdts :  102648.741372, dtrpr :  0.000000, ionxr :  19.831918, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  14, f :  0, rr :  23343648.060891, cdts :  102648.741372, dtrpr :  0.000000, ionxr :  19.831918, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  14, f :  1, rr :  23343648.060891, cdts :  102648.741372, dtrpr :  0.000000, ionxr :  35.563990, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  14, f :  1, rr :  23343648.060891, cdts :  102648.741372, dtrpr :  0.000000, ionxr :  35.563990, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  30, f :  0, rr :  21635324.825727, cdts : -127128.592610, dtrpr :  0.000000, ionxr :  14.159144, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
2024/03/05 05:50:01  sys:  1,prn:  30, f :  0, rr :  21635324.825727, cdts : -127128.592610, dtrpr :  0.000000, ionxr :  14.159144, dantr :  0.000000, dantrr[findex] :  0.000000, scb :  0.000000, 
"""

# 日志行数
LOG_LINE_NUM = 0


class MY_GUI():
    def __init__(self, init_window_name):
        self.init_window_name = init_window_name

    # 设置窗口
    def set_init_window(self):
        self.init_window_name.title("电离层绘制工具_v1.0 @wqh")  # 窗口名
        self.init_window_name.geometry('480x300+10+10')  # 290 160为窗口大小,+10 +10 定义窗口弹出时的默认展示位置
        # self.init_window_name["bg"] = "pink" # 窗口背景色,其他背景色见:blog.csdn.net/chl0000/article/details/7657887
        # self.init_window_name.attributes("-alpha",0.9) #虚化,值越小虚化程度越高
        # 标签
        self.init_data_label = Label(self.init_window_name, text="请输入展示的卫星片段数")
        self.init_data_label.grid(row=0, column=0)
        # self.result_data_label = Label(self.init_window_name, text="输出结果")
        # self.result_data_label.grid(row=0, column=12)
        self.log_label = Label(self.init_window_name, text="日志信息")
        self.log_label.grid(row=12, column=0)
        # 文本框
        self.init_data_Text = Entry(self.init_window_name, width=10)  # 卫星颗数录入框
        self.init_data_Text.insert(0, "10")  # 默认值
        self.init_data_Text.grid(row=0, column=0, rowspan=10, columnspan=10)
        # self.result_data_Text = Text(self.init_window_name, width=70, height=49)  # 处理结果展示
        # self.result_data_Text.grid(row=1, column=12, rowspan=15, columnspan=10)
        self.log_data_Text = Text(self.init_window_name, width=66, height=14)  # 日志框
        self.log_data_Text.grid(row=20, column=0, columnspan=10)
        # 按钮
        self.select_file_button = Button(self.init_window_name, text="选择文件", bg="lightblue", width=10,
                                         command=self.select_file)
        self.select_file_button.grid(row=100, column=1)
        self.start_drawing_button = Button(self.init_window_name, text="开始绘制", bg="lightblue", width=10,
                                           command=self.start_drawing)  # 调用内部方法  加()为直接调用
        self.start_drawing_button.grid(row=100, column=5)

    # 第一步,去重提取出指定列的数据
    def get_sys(self):
        # 用于存储去重后的数据
        unique_data = set()
        with open(self.file_path, 'r') as file:
            lines = file.readlines()
            # 因数据重复,隔行读取数据
            for line in lines[::2]:
                # 多个分隔符来分割
                temp = re.split("[,| ]+", line)
                # 提取指定的多列
                selected_columns = [temp[3], temp[5], temp[8]]
                # 将选定的列转换为元组,以便用于集合中的去重
                selected_columns_tuple = tuple(selected_columns)
                # 将元组添加到集合中
                unique_data.add(selected_columns_tuple)

        # 将集合转换回列表
        self.unique_data_list = list(unique_data)
        ll = len(self.unique_data_list)
        self.write_log_to_Text(f"完成文件的卫星数据筛选,总计{ll}条卫星片段")
        # print(self.unique_data_list)
        return self.unique_data_list

    # 第二步,根据指定的数据再统计、绘图
    def start_drawing(self):
        try:
            # 获取文件的卫星列表
            sys = self.get_sys()
            lss = len(sys)
            # 获取文本框输入的卫星颗数
            ef = int(self.init_data_Text.get())
            # 取输入的卫星颗数和文件的卫星颗数的小值
            ls = ef if ef < lss else lss

            with open(self.file_path, 'r') as file:
                lines = file.readlines()
                # 使用字典推导式生成对应数量的空列表和0,并为它们重新命名
                time_lists = {f'time_list_{i}': [] for i in range(ls)}
                #rr_lists = {f'rr_list_{i}': [] for i in range(ls)}
                #cdts_lists = {f'cdts_list_{i}': [] for i in range(ls)}
                #dtrpr_lists = {f'dtrpr_list_{i}': [] for i in range(ls)}
                ionxr_lists = {f'ionxr_list_{i}': [] for i in range(ls)}
                # count_lists = {f'count_list_{i}': 0 for i in range(ls)}
                # 因数据重复,隔行读取数据
                for line in lines[::2]:
                    # 多个分隔符来分割
                    temp = re.split("[,| ]+", line)
                    for j in range(0, ls):
                        if (temp[3] == str(sys[j][0])) & (temp[5] == str(sys[j][1])) & (temp[8] == str(sys[j][2])):
                            datee = temp[0]
                            timee = temp[1]
                            rr = temp[11]
                            cdts = temp[14]
                            dtrpr = temp[17]
                            ionxr = temp[20]
                            dt = datee + " " + timee
                            time_list = datetime.strptime(dt, "%Y/%m/%d %H:%M:%S")
                            time_lists['time_list_' + str(j)].append(time_list)
                            #rr_lists['rr_list_' + str(j)].append(rr)
                            #cdts_lists['cdts_list_' + str(j)].append(cdts)
                            #dtrpr_lists['dtrpr_list_' + str(j)].append(dtrpr)
                            ionxr_lists['ionxr_list_' + str(j)].append(ionxr)
                            # count_lists['count_list_' + str(j)] += 1
                            # print(time_lists['time_list_' + str(j)], ionxr_lists['ionxr_list_' + str(j)])

                # 画布设置,figsize属性来改变画布尺寸,dpi属性来改变画布分辨率
                plt.figure(figsize=(30, 8), dpi=600)
                # 设置x轴标签、y轴标签、标题
                plt.xlabel(u"UTC时间")
                plt.ylabel(u"电离层系数")
                plt.title(u'电离层活跃状况')

                # yindex = [-200, -150, -100, -50, 0, 50, 100, 150, 200]
                # plt.yticks(xindex, [ionxr_lists['ionxr_list_' + str(m)] for m in xindex])  # 自由显示刻度,xindex存一下要显示的刻度从0开始的下标即可
                # plt.yticks(yindex)
                # y轴不显示刻度
                plt.yticks([])

                if ls > 0:
                    # 开始绘图
                    self.write_log_to_Text(f"开始绘图,将会展示{ls}条卫星片段,请稍侯...")
                    # 绘制线形图
                    for j in range(ls):
                        # linewidth设置线条宽度
                        plt.plot(time_lists['time_list_' + str(j)], ionxr_lists['ionxr_list_' + str(j)], linewidth=1)
                        # print(count_lists['count_list_' + str(j)])
                else:
                    self.write_log_to_Text(f"输入的卫星数不正确,或者文件中没有匹配的卫星,请重试!")
                    pass

                # 保存图片
                timestamp = int(time.time())
                timestamp_str = str(timestamp)
                file_path = os.path.dirname(__file__)
                file_path_s = os.path.join(file_path, timestamp_str + '.jpg')
                plt.savefig(file_path_s)
                self.write_log_to_Text(f"图片存放的位置:{file_path_s}")

                # 清理释放内存
                plt.clf()
                plt.close()

                # # 显示图表
                # plt.show()

        except Exception as e:
            self.write_log_to_Text(f"请选择文件,再开始绘图,报错信息:{e}")
            # self.select_file()

    # 选择文件
    def select_file(self):
        self.file_path = filedialog.askopenfilename()
        # 判断文件名是否包含out_los
        if "out_los" in os.path.basename(self.file_path):
            # print(f"Selected file: {self.file_path}")
            self.write_log_to_Text(f"文件路径: {self.file_path}")
        else:
            self.write_log_to_Text(f"非out_los文件,请重新选择,原文件路径为: {self.file_path}")
            self.select_file()
        # return self.file_path

    # 获取当前时间
    def get_current_time(self):
        current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        return current_time

    # 日志动态打印
    def write_log_to_Text(self, logmsg):
        global LOG_LINE_NUM
        current_time = self.get_current_time()
        logmsg_in = str(current_time) + " " + str(logmsg) + "\n"  # 换行
        if LOG_LINE_NUM <= 7:
            self.log_data_Text.insert(END, logmsg_in)
            LOG_LINE_NUM = LOG_LINE_NUM + 1
        else:
            self.log_data_Text.delete(1.0, 2.0)
            self.log_data_Text.insert(END, logmsg_in)


def gui_start():
    init_window = Tk()  # 实例化出一个父窗口
    ZMJ_PORTAL = MY_GUI(init_window)
    # 设置根窗口默认属性
    ZMJ_PORTAL.set_init_window()

    init_window.mainloop()  # 父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示


gui_start()

工具界面:

保存的图片:

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值