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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()