You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fitt/newly_added/functions.py

144 lines
5.9 KiB

11 months ago
import tkinter as tk
from tkinter import messagebox
from collections import OrderedDict
from mpl_toolkits import axisartist
from sympy import sympify, SympifyError
from scipy.optimize import curve_fit
from tkinter import filedialog
import numpy as np
import matplotlib.pyplot as plt
from formula import expression_output
index = 1
def check_formula_syntax(formula):
try:
sympify(formula)
return True
except SympifyError:
return False
# 创建弹出窗口
def creat_window(title):
top = tk.Toplevel(Root)
top.geometry("300x350")
top.title(title)
return top
# 输入框
def create_input_box(top, text, value):
box_label = tk.Label(top, text=text)
box_label.pack(padx=10, pady=10)
box_size = tk.IntVar(top, value=value) # 创建一个IntVar对象并设置默认值为3
box_size_entry = tk.Entry(top, textvariable=box_size) # 关联IntVar对象
box_size_entry.pack(padx=20, pady=20)
return box_size_entry
def askfile():# 从本地选择一个文件,并返回文件的路径
global sampleData
# 弹出文件选择对话框,选择要打开的文本文件
file_path = filedialog.askopenfilename(filetypes=[('Text Files', '*.txt')])
# 如果没有选择文件,直接返回
if not file_path:
return
x, y = [], []#初始化xy
with open(file_path, 'r') as file:
for line in file:#逐行读文件
line = line.strip('\n')#移除换行符
sx, sy = line.split(' ')#以空格分割xy
x.append(float(sx))#将sx转换为浮点数并加入数组
y.append(float(sy))#将sy转换为浮点数并加入数组
X, Y = np.array(x), np.array(y)#xy数组转为array并赋值给全局变量
sampleData.append(X)
sampleData.append(Y)
print(sampleData)
def create_func(code_str):
# 创建一个空的命名空间
namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
exec(code_str, globals(), namespace)
# 返回命名空间中的函数对象
return namespace['func']
def draw_axis(low, high, step=250):
fig = plt.figure(figsize=(4.4, 3.2))
ax = axisartist.Subplot(fig, 111)# 使用axisartist.Subplot方法创建一个绘图区对象ax
fig.add_axes(ax)# 将绘图区对象添加到画布中
ax.axis[:].set_visible(False)# 通过set_visible方法设置绘图区所有坐标轴隐藏
ax.axis["x"] = ax.new_floating_axis(0, 0)# 添加新的x坐标轴
ax.axis["x"].set_axisline_style("-|>", size=1.0)# 给x坐标轴加上箭头
ax.axis["y"] = ax.new_floating_axis(1, 0)# 添加新的y坐标轴
ax.axis["y"].set_axisline_style("-|>", size=1.0)# y坐标轴加上箭头
ax.axis["x"].set_axis_direction("bottom")# 设置x、y轴上刻度显示方向
ax.axis["y"].set_axis_direction("left")# 设置x、y轴上刻度显示方向
plt.xlim(low, high) # 把x轴的刻度范围设置
plt.ylim(low, high) # 把y轴的刻度范围设置
ax.set_xticks(np.arange(low, high + 5, step))# 把x轴的刻度间隔设置
ax.set_yticks(np.arange(low, high + 5, step))# 把y轴的刻度间隔设置
def fitting():
global letters
askfile()
letters, result=expression_output(result2)
# print(letters,result)
# 定义要转换的字符串
code_str = '''
def func({}):
return {}
'''.format(letters,result)
# print(code_str)
my_func = create_func(code_str)
popt, pcov = curve_fit(my_func, sampleData[0], sampleData[1])# 用curve_fit来对点进行拟合
draw_axis(-1000, 1000) # 绘制坐标轴
positive_mask = sampleData[0] >= 0.0#给样本点分类
negative_mask = sampleData[1] < 0.0#给样本点分类
positive_colors = ['red' if x >= 0.0 else 'blue' for x in sampleData[0]]#给样本点分类
negative_colors = ['green' if x >= 0.0 else 'purple' for x in sampleData[0]]#给样本点分类
#根据样本点类型决定样本点颜色
plt.scatter(sampleData[0][positive_mask], sampleData[1][positive_mask], color=np.array(positive_colors)[positive_mask], lw=1)
plt.scatter(sampleData[0][negative_mask], sampleData[1][negative_mask], color=np.array(negative_colors)[negative_mask], lw=1)
curve_x = np.arange(-1000, 1000)#按照步长生成的一串数字
curve_y = [my_func(i, * popt) for i in curve_x]# 根据x来计算y1值
plt.plot(curve_x, curve_y, color='blue', label='Fitted Curve')#绘制拟合曲线
plt.savefig(r"dot5.png", facecolor='w') # 保存到本地
plt.legend()
plt.show()
def add():
top = creat_window('新增拟合函数') # 创建弹出窗口
function_entry = create_input_box(top, "拟合函数名称:", '') # 创建一个输入框,获取拟合函数名称
math_entry = create_input_box(top, "数学式:", '') # 创建一个输入框,获取数学式
def get_input(): # 创建
# 获取输入框的内容
global result1, result2
result1 = function_entry.get()
result2 = math_entry.get()
if result1 and result2:
if check_formula_syntax(result2):
top.destroy() # 关闭窗口
# fitting()
letters, result = expression_output(result2)
print(letters)
print(result)
else:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
messagebox.showinfo('提示','你未输入的完成!')
button = tk.Button(top, text="确定", command=get_input)
button.pack()
if __name__ == '__main__':
# 创建一个二维数组sampleData用于存储样本数据
sampleData = []
Root = tk.Tk()
window_width = 400 # 窗口的宽度
window_height = 350 # 窗口的高度
Root.title("函数拟合")
Root.geometry("400x350") # 设置窗口的大小和位置
button = tk.Button(Root,text='新增拟合函数',bg='blue',command=add)
button.place(x=250,y=10)
Root.mainloop()