2024/06/07
学习时长:4小时
代码行数:166行
博客数量:1篇
今天主要完成了python大作业的有关内容
散点图的曲线拟合:可视化界面实现
import tkinter as tk import numpy as np import re import os import matplotlib.pyplot as plt from scipy.optimize import curve_fit from tkinter import messagebox # 存储输入框的结果 entry_results_x = [] entry_results_y = [] def save_fit_results(x_data, y_data, params): # 将拟合的参数转换成函数表达式的形式 function_expression = 'y = {:.2f}x^4 + {:.2f}x^3 + {:.2f}x^2 + {:.2f}x + {:.2f}'.format(*params) with open("big_work/拟合记录.txt", "a",encoding="utf-8") as file: file.write("参数坐标 (x, y):\n") for x, y in zip(x_data, y_data): file.write("({:.2f}, {:.2f})\n".format(x, y)) file.write("\n拟合结果表达式:\n") file.write(function_expression + "\n\n") extremum_points = calculate_extremum_points(params) messagebox.showinfo("极值点", "拟合曲线的极值点为: " + str(extremum_points)) def save_function_results(function_expression, x, y): folder_name = "big_work/表达式生成记录" os.makedirs(folder_name, exist_ok=True) file_name = re.sub('[^A-Za-z0-9]+', '_', function_expression) # 保存函数表达式数据到文件 data_file_path = os.path.join(folder_name, "表达式.txt") with open(data_file_path, 'a',encoding="utf-8") as file: file.write("函数表达式: {}\n".format(function_expression)) # 保存函数图像到文件 image_file_path = os.path.join(folder_name, file_name+"_plot.png") plt.savefig(image_file_path) def add_entry(): height = 0 row = len(entry_results_x) // 21 entry_x = tk.Entry(canvas, font=('Arial', 10), width=5) entry_results_x.append(entry_x) entry_y = tk.Entry(canvas, font=('Arial', 10), width=5) entry_results_y.append(entry_y) entry_window_x = canvas.create_window((len(entry_results_x) - row * 21) * 50 + 100, 570 + row * 60, window=entry_x, anchor='center') entry_window_y = canvas.create_window((len(entry_results_y) - row * 21) * 50 + 100, 600 + row * 60, window=entry_y, anchor='center') def complex_func(x, a, b, c, d, e):#拟合曲线 return a*x**4 + b*x**3 + c*x**2 + d*x + e def calculate_extremum_points(params):#求极值 a, b, c, d, e = params extremum_x = -b / (4 * a) extremum_y = complex_func(extremum_x, a, b, c, d, e) extremum_type = "极小值" if a < 0 else "极大值" # 判断极值点类型 return extremum_x, extremum_y, extremum_type def plot_extremum_points(params): extremum_x, extremum_y,extremum_type = calculate_extremum_points(params) extremum_text = "极值点: {}:({:.2f}, {:.2f})".format(extremum_type,extremum_x, extremum_y) extremum_point_label = tk.Label(canvas, text=extremum_text, font=('Arial', 12), bg='ivory') extremum_point_window = canvas.create_window(50, 50, window=extremum_point_label, anchor='nw') extremum_point_label.update_idletasks() root.update() def fit_data(): x_data = [] y_data = [] for entry_x, entry_y in zip(entry_results_x, entry_results_y): x_value = entry_x.get() y_value = entry_y.get() if x_value and y_value: x_data.append(float(x_value)) y_data.append(float(y_value)) if len(x_data) < 5 or len(y_data) < 5: messagebox.showerror("Error", "请至少提供五个数据点用于拟合曲线!") return # 使用Scipy进行曲线拟合 params, _ = curve_fit(complex_func, x_data, y_data, p0=[1, 1, 1, 1, 1]) # 绘制原始数据和拟合曲线 plt.figure() plt.scatter(x_data, y_data, color='blue', label='Data points') plt.plot(np.linspace(min(x_data), max(x_data), 100), complex_func(np.linspace(min(x_data), max(x_data), 100), *params), color='red', label='Fitted curve: y = {:.2f}x^4 + {:.2f}x^3 + {:.2f}x^2 + {:.2f}x + {:.2f}'.format(params[0], params[1], params[2], params[3], params[4])) plt.legend() plt.xlabel('X') plt.ylabel('Y') plt.title('Fitting Result') # 保存图像并在画布上显示 plt.savefig("fit_plot.png") fit_image = tk.PhotoImage(file="fit_plot.png") fit_image_label = tk.Label(canvas, image=fit_image) fit_image_label.image = fit_image fit_image_window = canvas.create_window(650, 300, window=fit_image_label, anchor='center') # 调用保存函数 save_fit_results(x_data, y_data, params) if(var1.get()): messagebox.showinfo("Data Saved", "保存记录成功") plot_extremum_points(params) def plot_function(): function_expression = entry_function.get() x = np.linspace(-10, 10, 400) try: y = eval(function_expression) plt.figure() plt.plot(x, y, color='blue') plt.xlabel('X') plt.ylabel('Y') plt.title('Function Plot: ' + function_expression) # 保存图像并在画布上显示 plt.savefig("function_plot.png") function_image = tk.PhotoImage(file="function_plot.png") function_image_label = tk.Label(canvas, image=function_image) function_image_label.image = function_image function_image_window = canvas.create_window(650, 300, window=function_image_label, anchor='center') # 调用保存函数 if(var1.get()): save_function_results(function_expression, x, y) messagebox.showinfo("Function Plotted", "保存文件成功") except Exception as e: messagebox.showerror("Error", "无法绘制该函数,请检查输入是否正确!") root = tk.Tk() root.geometry('1300x900') root.title('散点拟合器') canvas = tk.Canvas(root, width=1300, height=900, bg='ivory') button_fit = tk.Button(canvas, width=20, height=4, bg='ivory', text="开始拟合", command=fit_data) button_fit_window = canvas.create_window(400, 800, window=button_fit, anchor='s') add_button = tk.Button(canvas, text="添加点坐标", command=add_entry) add_button_window = canvas.create_window(400, 710, window=add_button, anchor='s') x_text = tk.Label(canvas, text="横坐标:", width=5, height=2, font=('Arial', 12), bg='ivory') x_text_window = canvas.create_window(80, 570, window=x_text, anchor='center') y_text = tk.Label(canvas, text="纵坐标:", width=5, height=2, font=('Arial', 12), bg='ivory') y_text_window = canvas.create_window(80, 600, window=y_text, anchor='center') fun_draw=tk.Label(canvas, text="函数表达式:", width=12, height=2, font=('Arial', 12), bg='ivory') fun_draw_s = canvas.create_window(800, 700, window=fun_draw, anchor='center') entry_function = tk.Entry(canvas, font=('Arial', 10), width=20) entry_function_window = canvas.create_window(920, 700, window=entry_function, anchor='center') var1 = tk.IntVar()#勾选保存 checkbutton1 = tk.Checkbutton(canvas, text="保存记录", variable=var1,bg='ivory') checkbutton1_window = canvas.create_window(600, 700, window=checkbutton1, anchor='nw') plot_button = tk.Button(canvas, width=20, height=4, bg='ivory', text="绘制函数", command=plot_function) plot_button_window = canvas.create_window(870, 800, window=plot_button, anchor='s') canvas.pack() root.mainloop()