更新代码

master
bettleChen 11 months ago
parent 61e620d19d
commit 88717d8f06

@ -23,6 +23,7 @@ def compute_curveData(num, step, coefficient): # coefficient代表二次函数
y_values = quadratic_function(x_values) # 调用quadratic_function(x)函数得到y值 y_values = quadratic_function(x_values) # 调用quadratic_function(x)函数得到y值
curve_data = np.column_stack((x_values, y_values)) # 将两个一维数组堆叠成二维数组,形成(x,y)的形式 curve_data = np.column_stack((x_values, y_values)) # 将两个一维数组堆叠成二维数组,形成(x,y)的形式
return curve_data return curve_data
if __name__ == '__main__': if __name__ == '__main__':
coefficient = [1, 2, 3] coefficient = [1, 2, 3]
ans = compute_curveData(1000, 250, coefficient) ans = compute_curveData(1000, 250, coefficient)

545
X5.py

@ -3,7 +3,7 @@
# Author : lirunsheng # Author : lirunsheng
# User : l'r's # User : l'r's
# Software: PyCharm # Software: PyCharm
# File : X4.py # File : X5.py
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
""" """
@ -12,88 +12,192 @@
@DateTime: 2023/5/30 15:29 @DateTime: 2023/5/30 15:29
@SoftWare: PyCharm @SoftWare: PyCharm
""" """
import random
import re
from tkinter import messagebox
import pandas as pd
from sympy import sympify, SympifyError
import sys import sys
from fitting import * from fitting import *
import numpy as np import numpy as np
import data as gl_data import data as gl_data
import input import input
import tkinter as tk import tkinter as tk
from tkinter import ttk
from tkinter import * from tkinter import *
from screeninfo import get_monitors
import os
from PIL import ImageTk, Image
import tkinter.filedialog # 注意次数要将文件对话框导入 import tkinter.filedialog # 注意次数要将文件对话框导入
# from demo1 import Addfunc # from demo1 import Addfunc
from newly_added.formula import *
from scipy.optimize import leastsq
global Q_root,F_root global Q_root,F_root
global root_window global root_window
global label1,label2,label3 global label1,label2,label3
class Addfunc():
def __init__(self): # 创建弹出窗口
self.r = 7.5 # 设置按钮大小 def creat_window(title):
self.rr = 2.5# 设置按钮大小 top = tk.Toplevel(root_window)
self.window = tk.Tk() # 新建函数增加窗口 top.geometry("300x350")
self.window.title("新增函数曲线")#设置窗口标题 top.title(title)
self.window.geometry('400x300')#设置窗口大小 return top
self.show()#显示按钮
self.window.mainloop()#运行UI界面 # 输入框
def create_input_box(top, text, value):
def show(self): box_label = tk.Label(top, text=text)
for widget in self.window.winfo_children(): box_label.pack(padx=10, pady=10)
widget.destroy()#清空已有组件 box_size = tk.IntVar(top, value=value) # 创建一个IntVar对象并设置默认值为3
self.add_cv = tk.Canvas(self.window, width=400, height=300) # 新建画布 box_size_entry = tk.Entry(top, textvariable=box_size) # 关联IntVar对象
self.add_cv.place(x=0, y=0) # 放置画布 box_size_entry.pack(padx=20, pady=20)
cur = 0#记录已有按钮个数 return box_size_entry
for f in function.Fun:#遍历已有函数
self.add_cv.create_oval(20 - self.r, 20 + 15 + cur * 30 - self.r, 20 + self.r, 20 + 15 + cur * 30 + self.r def check_formula_syntax(formula):
, fill="white", width=1, outline="black")# 绘制圆圈 try:
if f.show == 1:#若为当前选中函数,则标记 sympify(formula)
self.add_cv.create_oval(20 - self.rr, 20 + 15 + cur * 30 - self.rr, 20 + self.rr, 20 + 15 + cur * 30 + self.rr return True
, fill="black", width=1, outline="black") except SympifyError:
button = tk.Button(self.window, text=f.name + f.demo, bd=0, font=("微软雅黑", 12) return False
, command=lambda x=f.no: self.change(x), anchor=W)#设置选择按钮 def create_func(code_str):
button.place(x=40, y=20 + cur * 30, width=300, height=30)#放置选择按钮 # 创建一个空的命名空间
cur += 1#计数加一 namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
def change(self, no):#切换函数显示情况 exec(code_str, globals(), namespace)
function.Show[no] = not function.Show[no] # 返回命名空间中的函数对象
function.Fun[no].show = not function.Fun[no].show return namespace['func']
self.show()#更新函数选择面板
f_button()#更新函数显示界面 def fitting(letters,result):
# class AddFunc(Addfunc): code_str = '''
# def change(self, no): def func({}):
# # super().change(no) return {}
# function.Show[no] = not function.Show[no] '''.format(letters,result)
# function.Fun[no].show = not function.Fun[no].show return code_str
# self.show() # 更新函数选择面板
# f_button() def save(result1, letters, result , result2):
gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
gl_data.FITT_SAVE['no'][gl_data.INDEX] = gl_data.INDEX
gl_data.FITT_SAVE['name'][gl_data.INDEX] = result1
gl_data.FITT_SAVE['variable'][gl_data.INDEX] = letters
gl_data.FITT_SAVE['function'][gl_data.INDEX] = result
gl_data.FITT_SAVE['demo'][gl_data.INDEX] = result2
file_path = 'functions_new.xlsx'#设置路径
# 将字典转换为DataFrame
df = pd.DataFrame(gl_data.FITT_SAVE)
# 将DataFrame保存为Excel文件
df.to_excel(file_path, index=False)
def read_fitting():
file_path = 'functions_new.xlsx' # 设置路径
df = pd.read_excel(io=file_path, header=0) # 设置表格
gl_data.FITT_SAVE = df.to_dict()
def create_func(code_str):
# 创建一个空的命名空间
namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
exec(code_str, globals(), namespace)
# 返回命名空间中的函数对象
return namespace['func']
def addfunc(): def addfunc():
Addfunc() top = creat_window('新增拟合函数') # 创建弹出窗口
# AddFunc() function_entry = create_input_box(top, "拟合函数名称:", '') # 创建一个输入框,获取拟合函数名称
math_entry = create_input_box(top, "数学式:", '') # 创建一个输入框,获取数学式
def get_input(): # 创建
# 获取输入框的内容
result1 = function_entry.get()
result2 = math_entry.get()
if result1 and result2:
if check_formula_syntax(result2):
top.destroy() # 关闭窗口
letters, result = expression_output(result2)
save(result1, letters, result, result2)
gl_data.Xian_index = gl_data.INDEX
f_button()
else:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
messagebox.showinfo('提示','你未输入的完成!')
button = tk.Button(top, text="确定", command=get_input)
button.pack()
def jis():
global screen_size
# 获取当前屏幕的宽度和高度
monitors = get_monitors()
screen_width = monitors[0].width
# 计算按钮的宽度和高度
button_width = int(screen_width * 0.85)
# 打印按钮的宽度和高度
screen_size = round(button_width*0.9/900, 1)
gl_data.MAGNIDICATION = screen_size
read_fitting()
def element1(path):
# print(path)
# 加载图像并创建一个 PhotoImage 对象
image = tk.PhotoImage(file=path)
# 保存图片的引用,防止被垃圾回收
root_window.image = image
return image
def element(path, width, height):
# 加载图元对应的图片文件
img = Image.open(path)
# # 使用resize方法调整图片
img = img.resize((width, height))
# 把Image对象转换成PhotoImage对象
img = ImageTk.PhotoImage(img)
# 保存图片的引用,防止被垃圾回收
root_window.img = img
return img
def window(): def window():
global root_window global root_window
global label1, label2, label3 global label1, label2, label3
root_window = Tk() root_window = Tk()
root_window.title('函数拟合') root_window.title('函数拟合')
root_window.geometry('900x600') # 设置窗口大小:宽x高,注,此处不能为 "*",必须使用 "x" width, height = int(900*screen_size), int(560*screen_size)
root_window.geometry(str(width)+'x'+str(height)) # 设置窗口大小:宽x高,注,此处不能为 "*",必须使用 "x"
# 设置主窗口的背景颜色,颜色值可以是英文单词或者颜色值的16进制数,除此之外还可以使用Tk内置的颜色常量 # 设置主窗口的背景颜色,颜色值可以是英文单词或者颜色值的16进制数,除此之外还可以使用Tk内置的颜色常量
root_window["background"] = "white" img_path = ["background/add.png", "background/下方输入框.png", "background/右侧未选中.png", "background/右侧背景.png",
"background/右侧选中.png","background/大背景.png", "background/导航拦.png", "background/导航输入框.png",
"background/小直线.png", "background/手动输入数据集.png", "background/拟合.png", "background/新增拟合曲线类型.png",
"background/显示数据集与曲线.png", "background/未选中.png", "background/生成数据集.png", "background/矩形.png",
"background/背景图片.png", "background/装载.png", "background/选中.png", "background/显示数据集.png",
"background/img.png"
]
global list_image
list_image = []
for i in range(len(img_path)):
if i in [17, 14, 19, 10, 12]:
list_image.append(element(img_path[i], 110, 80))
elif i == 16:
list_image.append(element(img_path[i], width, height))
elif i in [11, 9]:
list_image.append(element(img_path[i], 240, 80))
else:
list_image.append(element1(img_path[i]))
# root_window["background"] = "#87ceeb"
canvas = tk.Canvas(root_window, width=width-10, height=int(560*screen_size)-10)
canvas.place(x=0, y=0)
canvas.create_image(0, 0, image=list_image[16], anchor=tk.NW)
root_window.resizable(0, 0) # 防止用户调整尺寸 root_window.resizable(0, 0) # 防止用户调整尺寸
label1 = tk.Label(root_window, text="样本数据\n集文件", font=('Times', 8), bg="white", canvas.create_text(int(40*screen_size), int(26*screen_size), text='样本数据\n集文件', font='Arial 14', fill='black')
width=13, height=3, # 设置标签内容区大小 label3 = tk.Label(root_window, text="", font=('Times', 12), bg="#ADD8E6", fg="black",
padx=0, pady=0, borderwidth=0, ) width=50, height=3, padx=0, pady=0, borderwidth=0, relief="ridge", highlightcolor="blue")
label1.place(x=10, y=4) # 设置填充区距离、边框宽度和其样式(凹陷式) label3.place(x=int(122*screen_size), y=int(10*screen_size))
label3 = tk.Label(root_window, text="", font=('Times', 8), bg="white", fg="black",
width=39, height=2, padx=0, pady=0, borderwidth=0, relief="ridge", highlightcolor="blue")
label3.place(x=122, y=10)
# 使用按钮控件调用函数 # 使用按钮控件调用函数
tk.Button(root_window, text="装载", relief=RAISED, command=lambda: askfile()).place(x=370, y=12) tk.Button(root_window, image=list_image[17], relief=tk.FLAT, bd=0, command=lambda: askfile()).place(x=int(490*screen_size), y=int(12*screen_size))
label2 = tk.Label(root_window, text="拟合曲线类型", font=('Times', 12), bg="white", canvas.create_text(int(610*screen_size), int(40 * screen_size), text='拟合曲线类型', font='Arial 14', fill='black')
width=20, height=3, # 设置标签内容区大小 gl_data.Canvas2 = tk.Canvas(root_window, bg='white', width=int(550*screen_size), height=int(330*screen_size))
padx=0, pady=0, borderwidth=0, ) gl_data.Canvas2.place( x=int(4*screen_size), y=int(60*screen_size))
# 设置填充区距离、边框宽度和其样式(凹陷式)
label2.place(x=450, y=4) canvas.create_text(int(60*screen_size), int(490*screen_size),text="结果输出:", font='Arial 16', fill='black')
gl_data.Canvas2 = tk.Canvas(root_window, bg='white', width=450, height=330)
gl_data.Canvas2.place(x=4, y=60)
# 定义一个处理文件的相关函数 # 定义一个处理文件的相关函数
def askfile(): def askfile():
# 从本地选择一个文件,并返回文件的路径 # 从本地选择一个文件,并返回文件的路径
@ -125,51 +229,56 @@ def read_sample_data(file_path):
def buttons(): def buttons():
# 随机生成样本点并显示 # 随机生成样本点并显示
b_dot = tk.Button(root_window, text="生成\n数据集", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10), b_dot = tk.Button(root_window, image=list_image[14], relief=tk.FLAT, bd=0, command=lambda: generate_and_plot_sample_data(gl_data.LOW, gl_data.HIGH))
command=lambda: generate_and_plot_sample_data(gl_data.LOW, gl_data.HIGH)) b_dot.place(x=int(435*screen_size), y=int(410*screen_size))
b_dot.place(x=455, y=410)
# 显示当前样本点 # 显示当前样本点
b_show = tk.Button(root_window, text="显示\n数据集", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10), b_show = tk.Button(root_window, image=list_image[19], relief=tk.FLAT, bd=0, command=lambda: selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH))
command=lambda: selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH)) b_show.place(x=int(515*screen_size), y=int(410*screen_size))
b_show.place(x=510, y=410)
# 显示数据集与曲线 # 显示数据集与曲线
b_line = tk.Button(root_window, text="显示数据\n集与曲线", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10), b_line = tk.Button(root_window, image=list_image[12], relief=tk.FLAT, bd=0, command=lambda: draw_dots_and_line(gl_data.Xian_index, gl_data.LOW, gl_data.HIGH,
command=lambda: draw_dots_and_line(gl_data.Xian_index, gl_data.LOW, gl_data.HIGH, gl_data.X, gl_data.Y)) gl_data.X, gl_data.Y))
b_line.place(x=565, y=410) b_line.place(x=int(595*screen_size), y=int(410*screen_size))
# 手动输入数据集 # 手动输入数据集
b_input = tk.Button(root_window, text="手动输入数据集", relief=RAISED, bd=4, bg="white", pady=7, font=("微软雅黑", 13), b_input = tk.Button(root_window, image=list_image[9], relief=tk.FLAT, bd=0, command=lambda: input.input_num(root_window))
command=lambda: input.input_num(root_window)) b_input.place(x=int(675*screen_size), y=int(410*screen_size))
b_input.place(x=633, y=410)
# 拟合并输出拟合结果 # 拟合并输出拟合结果
b_fit = tk.Button(root_window, text="拟合", relief=RAISED, bd=4, bg="white", pady=7, font=("微软雅黑", 13), b_fit = tk.Button(root_window, image=list_image[10], relief=tk.FLAT, bd=0, command=lambda: fit_data(gl_data.Xian_index, gl_data.X, gl_data.Y))
command=lambda: fit_data(gl_data.Xian_index, gl_data.X, gl_data.Y)) b_fit.place(x=int(821*screen_size), y=int(410*screen_size))
b_fit.place(x=771, y=410)
def show_fit(): def show_fit():
L = tk.Label(root_window, text='结果输出:', bg='white', font=("微软雅黑", 16)
, anchor=W)
L.place(x=20, y=480, width=100, height=30)
sout = str(gl_data.Out) sout = str(gl_data.Out)
ans = tk.Label(root_window, text=sout, font=("微软雅黑", 14) ans = tk.Label(root_window, text=sout, font=("微软雅黑", 14)
, anchor=W, justify='left') , anchor=W, justify='left')
ans.place(x=120, y=480, width=760, height=100) ans.place(x=int(120*screen_size), y=int(480*screen_size), width=int(760*screen_size), height=100)
print(sout) print(sout)
def fit_data(xian_index, sx, sy): def fit_data(xian_index, sx, sy):
# gl_data.yvals_pow = [] if gl_data.Quadrant:
cur = function.Fun[xian_index] # 装载正在选择的函数 x = sx.tolist()
func = cur.get_fun()#获取当前函数func y = sy.tolist()
popt, pcov = curve_fit(func, sx, sy)# 用curve_fit来对点进行拟合 negative_x = [i for i, num in enumerate(x) if num < 0]
negative_y = [i for i, num in enumerate(y) if num < 0]
negative = list(set(negative_x + negative_y))
for index in range(len(negative)):
# print(negative[-index-1])
x.pop(negative[-index-1])
y.pop(negative[-index-1])
sx = np.array(x)
sy = np.array(y)
letters, result = gl_data.FITT_SAVE['variable'][xian_index], gl_data.FITT_SAVE['function'][xian_index]
code_str = fitting(letters, result)
func = create_func(code_str) # 获取当前函数func
popt, pcov = curve_fit(func, sx, sy) # 用curve_fit来对点进行拟合
yvals_pow = func(gl_data.X, *popt) yvals_pow = func(gl_data.X, *popt)
rr = gl_data.goodness_of_fit(yvals_pow, gl_data.Y)# 计算本次拟合的R*R值用于表示拟合优度 rr = gl_data.goodness_of_fit(yvals_pow, gl_data.Y)# 计算本次拟合的R*R值用于表示拟合优度
# 输出拟合后的各个参数值 # 输出拟合后的各个参数值
ans = '\n函数系数:' ans = '\n函数系数F(x) = '
for i in range(cur.variable): letter = str(letters[2:]).split(',')
if i == 4: pattern = re.compile('|'.join(letter))
ans += '\n' s = pattern.sub('{:.2f}', gl_data.FITT_SAVE['demo'][xian_index])
if i != 0: ans += str(s.format(*popt))
ans += ', ' gl_data.Out = '函数形式:' + gl_data.FITT_SAVE['name'][xian_index] + ' '
ans += chr(ord('a') + i) + '=' + '{:.2e}'.format(popt[i]) # str(round(gl_data.popt[i], 3)) gl_data.Out += gl_data.FITT_SAVE['demo'][xian_index]
gl_data.Out = '函数形式:' + cur.name + ' '
gl_data.Out += cur.demo
gl_data.Out += ans gl_data.Out += ans
gl_data.Out += '\n拟合优度(R\u00b2)' + str(round(rr, 5)) gl_data.Out += '\n拟合优度(R\u00b2)' + str(round(rr, 5))
show_fit()# 显示函数信息到输出框 show_fit()# 显示函数信息到输出框
@ -187,79 +296,253 @@ def q_button():
rr = 2.5 rr = 2.5
for widget in Q_root.winfo_children(): for widget in Q_root.winfo_children():
widget.destroy() widget.destroy()
q_cv = tk.Canvas(Q_root, width=400, height=50) q_cv = tk.Canvas(Q_root, width=int(400*screen_size), height=int(50*screen_size))
q_cv.place(x=0, y=0) q_cv.place(x=0, y=0)
l = tk.Label(Q_root, text='坐标轴', bd=0, font=("微软雅黑", 16) # q_cv.create_image(0, 0, image=list_image[20], anchor=tk.NW)
, anchor=W) l = tk.Label(Q_root, text='坐标轴', bd=0, font=("微软雅黑", 16), anchor=W)
l.place(x=20, y=0, width=80, height=50,) l.place(x=20, y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 四象限按钮 # 四象限按钮
b1 = tk.Button(Q_root, text='四象限', bd=0, font=("微软雅黑", 16) b1 = tk.Button(Q_root, text='四象限', bd=0, font=("微软雅黑", 16)
, command=lambda: change_Q(0), anchor=W) , command=lambda: change_Q(0), anchor=W)
b1.place(x=170, y=0, width=80, height=50,) b1.place(x=int(170*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 一象限按钮 # 一象限按钮
b2 = tk.Button(Q_root, text='一象限', bd=0, font=("微软雅黑", 16) b2 = tk.Button(Q_root, text='一象限', bd=0, font=("微软雅黑", 16)
, command=lambda: change_Q(1), anchor=W) , command=lambda: change_Q(1), anchor=W)
b2.place(x=320, y=0, width=80, height=50,) b2.place(x=int(320*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 绘制标记框 # # 绘制标记框
q_cv.create_oval(140 - r, 25 - r, 140 + r, 25 + r q_cv.create_image(int((145 - r)*screen_size), int((35 - r)*screen_size),
, fill="white", width=1, outline="black") image=list_image[2])
q_cv.create_oval(290 - r, 25 - r, 290 + r, 25 + r q_cv.create_image(int((295 - r)*screen_size), int((35 - r)*screen_size),
, fill="white", width=1, outline="black") image=list_image[2])
# 根据当前的象限选择值来填充标记框 # 根据当前的象限选择值来填充标记框
if gl_data.Quadrant == 0: if gl_data.Quadrant == 0:
q_cv.create_oval(140 - rr, 25 - rr, 140 + rr, 25 + rr q_cv.create_image(int((140 - rr)*screen_size), int((30 - rr)*screen_size),
, fill="black", width=1, outline="black") image=list_image[18])
else: else:
q_cv.create_oval(290 - rr, 25 - rr, 290 + rr, 25 + rr q_cv.create_image(int((290 - rr)*screen_size), int((30 - rr)*screen_size),
, fill="black", width=1, outline="black") image=list_image[18])
def change_f(no): def change_f(no):
gl_data.Xian_index = no#设置全局函数编号为该函数 gl_data.Xian_index = no#设置全局函数编号为该函数
f_button()#重新绘制函数显示界面 f_button()#重新绘制函数显示界面
def f_button(): def f_button():
r = 7.5#设置按钮大小 r = 7.5 # 设置按钮大小
rr = 2.5#设置按钮大小 rr = 2.5 # 设置按钮大小
for widget in F_root.winfo_children(): for widget in F_root.winfo_children():
widget.destroy()#清空原有按钮 widget.destroy() # 清空原有按钮
f_cv = tk.Canvas(F_root, width=400, height=330)#新建画布 gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
f_cv.place(x=0, y=0)#放置画布 canvas = Canvas(F_root, width=int(320 * screen_size), height=int(270 * screen_size))
f_cv.create_rectangle(2, 2, 398, 328, fill='white', outline="#0099ff")#设置画布边框及底色 # # 将图像添加到 Canvas 组件中
cur = 0#函数计数 canvas.pack(side="left", fill="both", expand=True)
for fun in function.Fit_type_library:#遍历函数库 scrollbar = Scrollbar(F_root, orient="vertical", command=canvas.yview)
f = function.Fit_type_library.get(fun)#获取函数具体信息 scrollbar.pack(fill="y", side="right")
if function.Show[f[0]] == 1:# 如果show为1则显示 canvas.configure(yscrollcommand=scrollbar.set)
f_cv.create_oval(20 - r, 20 + 15 + cur * 30 - r, 20 + r, 20 + 15 + cur * 30 + r canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
, fill="white", width=1, outline="black")# 绘制标记框 if gl_data.INDEX - 10 <= 0:
if f[0] == gl_data.Xian_index:# 若选择为当前函数则标记 result = 0
f_cv.create_oval(20 - rr, 20 + 15 + cur * 30 - rr, 20 + rr, 20 + 15 + cur * 30 + rr else:
, fill="black", width=1, outline="black") result = gl_data.INDEX - 10
canvas_height = int(328 * screen_size) + result*50 # 或根据需要调整适当的高度增加值
# # 绘制矩形边框及底色
canvas.create_rectangle(2, 2, int(398 * screen_size), canvas_height, fill='#ADD8E6', outline="#0099ff")
# canvas.create_image(4, 4, image=list_image[3], anchor=tk.NW)
cur = 0 # 函数计数
for i in range(gl_data.INDEX): # 遍历函数库
if gl_data.FITT_SAVE['no'][i] == gl_data.Xian_index: # 若选择为当前函数则标记
# 在指定位置绘制图片
canvas.create_image(int((20 - rr) * screen_size), int((20 + 15 + cur * 30 - rr) * screen_size), image=list_image[4])
else:
# 在指定位置绘制图片
canvas.create_image(int((20 - rr) * screen_size), int((20 + 15 + cur * 30 - rr) * screen_size),
image=list_image[2])
# 绘制切换按钮,单击则将当前使用函数切换为该函数 # 绘制切换按钮,单击则将当前使用函数切换为该函数
button = tk.Button(F_root, text=f[2] + ' ' + f[1], bd=0, bg="white", font=("微软雅黑", 12) button = tk.Button(F_root, text=gl_data.FITT_SAVE['name'][i] + ' ' + gl_data.FITT_SAVE['demo'][i], bd=0,
, command=lambda x=f[0]: change_f(x), anchor=W) bg="#ADD8E6", font=("微软雅黑", 10),
button.place(x=40, y=20 + cur * 30, width=300, height=30) command=lambda x=gl_data.FITT_SAVE['no'][i]: change_f(x), anchor=W)
cur += 1#计数加一 # 将按钮放置在Canvas中
canvas.create_window(int(40 * screen_size), int((30 + cur * 30) * screen_size), window=button, anchor="w")
cur += 1 # 计数加一
canvas.configure(scrollregion=canvas.bbox("all"))
def close_window(): def close_window():
sys.exit() sys.exit()
def functional_formula(letter,result,decimals):
# 使用 zip() 函数将两个列表组合成元组的迭代器
pairs = zip(letter, decimals)
# 使用字典推导式构建字典
target = {key: str(value) for key, value in pairs}
# print(target)
# # 依次替换字符串中的元素
for key, value in target.items():
indices = [i for i, c in enumerate(result) if c == key]
for i in indices:
if (i + 1) == len(result) or result[i + 1] in ['*', '+', '-', '/', ')', '']:
result = result[0:i] + value + result[i + 1:]
return result
def make_func(letters,result):
# print(letters,result)
letter = str(letters).split(',')
n = len(letter)-1
decimals = [round(random.uniform(-10, 10), 1) for _ in range(n)]
target_result = functional_formula(letter[1:], result, decimals)
# 清除以前的值
entry3.delete(0, tk.END)
# 填入函数
entry3.insert(0, target_result)
code_str = fitting('x', target_result)
target_func = create_func(code_str) # 获取当前函数func
curve_func(target_func)
def curve_func(func):
# 绘制拟合结果
draw_axis(-100, 100, 20)
x_fit = np.linspace(-100, 100, 100)
y_fit = func(x_fit)
plt.plot(x_fit, y_fit, 'r-', label='拟合曲线')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
# plt.show()
plt.savefig('new_line.png')
# 清除当前图形状态
plt.clf()
show_image()
def show_image():
# 加载图像
image = Image.open("new_line.png")
image = image.resize((500, 500))
# 在画布上显示图像
image_tk = ImageTk.PhotoImage(image)
root_window.image_tk = image_tk
show_canvas.create_image(0, 0, anchor="nw", image=image_tk)
def add_func():
result1 = entry1.get()
result2 = entry2.get()
if result1 and result2:
if check_formula_syntax(result2):
letters, result = expression_output(result2)
if result == None:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
make_func(letters,result)
else:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
messagebox.showinfo('提示','你未输入的完成!')
def customized_curve():
result1 = entry2.get()
result2 = entry3.get()
if result1 and result2:
if check_formula_syntax(result1):
letters, result = expression_output(result1)
if result == None:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
# 删除空格
result2 = result2.replace(' ', '')
# 使用正则表达式替换数字为空字符串
result3 = re.sub(r'[-]?\d+(\.\d+)?', '', result2)
letter = str(letters).split(',')
decimals = [1 for _ in range(len(letter)-1)]
result4 = functional_formula(letter[1:], result, decimals)
result4 = result4.replace('1', '')
result4 = re.sub(r'[-]?\d+(\.\d+)?', '', result4)
result4 = result4.replace(' ', '')
# print(result3,result4)
if result3 == result4:
code_str = fitting('x', result2)
func = create_func(code_str) # 获取当前函数func
curve_func(func)
else:
messagebox.showinfo('提示', '请检查你修改的函数是否与函数式相对应!')
def func_save():
result1 = entry1.get()
result2 = entry2.get()
if result1 and result2:
if check_formula_syntax(result2):
letters, result = expression_output(result2)
if result== None:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
save(result1, letters, result, result2)
subwindow.destroy() # 关闭子页面
gl_data.Xian_index = gl_data.INDEX
f_button()
else:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
messagebox.showinfo('提示', '你未输入的完成!')
def show_subwindow():
global subwindow
subwindow = tk.Toplevel(root_window)
subwindow.geometry('1000x500')
subwindow.title('新增拟合函数')
# 创建画布
global show_canvas
canvas_width = 1000
canvas_height = 500
canvas = Canvas(subwindow, width=canvas_width, height=canvas_height, bg="#ADD8E6")
canvas.pack()
show_canvas = Canvas(canvas, width=600, height=500, bg="white")
show_canvas.place(x=0, y=0)
global entry1, entry2, entry3
# 创建输入框
label1 = tk.Label(canvas, text="函数名:")
label1.place(x=650, y=50)
entry1 = tk.Entry(canvas)
entry1.place(x=650, y=100, width=300, height=40)
label2 = tk.Label(canvas, text="函数式:")
label2.place(x=650, y=150)
entry2 = tk.Entry(canvas)
entry2.place(x=650, y=200, width=300, height=40)
label3 = tk.Label(canvas, text="测试函数式:")
label3.place(x=650, y=250)
entry3 = tk.Entry(canvas)
entry3.place(x=650, y=300, width=300, height=40)
button1 = tk.Button(canvas, text="生成函数", command=add_func)
button1.place(x=650, y=400)
button2 = tk.Button(canvas, text="函数曲线", command=customized_curve)
button2.place(x=750, y=400)
button3 = tk.Button(canvas, text="函数确认", command=func_save)
button3.place(x=850, y=400)
# subwindow.mainloop()
def main(): def main():
global Q_root, F_root,root_window global Q_root, F_root,root_window
jis()
# gl_data.LOW, gl_data.HIGH = int(gl_data.LOW*screen_size), int(gl_data.HIGH*screen_size)
gl_data.X = [] gl_data.X = []
gl_data.X = [] gl_data.X = []
window() window()
# 函数选择相关界面 # 函数选择相关界面
F_root = tk.Frame(root_window, width=400, height=330, bg='white', ) F_root = tk.Canvas(root_window, width=int(310*screen_size), height=int(290*screen_size))
F_root.place(x=490, y=60) F_root.place(x=int(560*screen_size), y=int(60*screen_size))
# 象限选择相关界面 # 象限选择相关界面
Q_root = tk.Frame(root_window, width=400, height=50, bg='white', ) Q_root = tk.Canvas(root_window, width=int(400*screen_size), height=int(50*screen_size))
Q_root.place(x=20, y=410) Q_root.place(x=int(20*screen_size), y=int(410*screen_size))
function.f_read()
buttons() buttons()
f_button() f_button()
q_button() q_button()
show_fit() show_fit()
tk.Button(root_window, text="新增拟合曲线类型", bd=4, command=addfunc).place(x=740, y=12) tk.Button(root_window, image=list_image[11], command=show_subwindow, relief=tk.FLAT, highlightthickness=0).place(x=int(640*screen_size), y=int(350)*screen_size)
# 设置Grid布局的列和行权重
root_window.protocol("WM_DELETE_WINDOW", close_window) root_window.protocol("WM_DELETE_WINDOW", close_window)
root_window.mainloop() root_window.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
pass pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -9,7 +9,8 @@ import tkinter as tk
from tkinter import * from tkinter import *
import random import random
import numpy as np import numpy as np
FITT_SAVE = {}
FITT_LIST = []
X = [] # 等待拟合的x值 X = [] # 等待拟合的x值
Y = [] # 等待拟合的y值 Y = [] # 等待拟合的y值
global Canvas2 # 用于显示函数的画布 global Canvas2 # 用于显示函数的画布
@ -18,10 +19,11 @@ Img2 = None # 绘制的line.png图像
Xian_index = 0 # 当前选择的函数编号 Xian_index = 0 # 当前选择的函数编号
Quadrant = 0 # 当前选择的象限信息0为四象限1为一象限 Quadrant = 0 # 当前选择的象限信息0为四象限1为一象限
MAXV = 1000 # 最大值 MAXV = 1000 # 最大值
INDEX = 5 # 拟合函数索引
Out = '' # 拟合输出信息 Out = '' # 拟合输出信息
LOW = -MAXV # 坐标轴显示上界 LOW = -MAXV # 坐标轴显示上界
HIGH = MAXV # 坐标轴显示下界 HIGH = MAXV # 坐标轴显示下界
MAGNIDICATION = 1.0 # 放大倍数
def random_points(): def random_points():
x=[] x=[]

@ -0,0 +1,10 @@
def func_save():
···与add_func相似
else:
save(result1, letters, result, result2)
subwindow.destroy() # 关闭子页面
gl_data.Xian_index = gl_data.INDEX
f_button()
tk.Button(root_window, text="新增拟合曲线类型",
bd=4, command=show_subwindow).place(
x=int(740*screen_size), y=int(12)*screen_size)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@ -13,7 +13,7 @@ import pylab as mpl
from tkinter import * from tkinter import *
import mpl_toolkits.axisartist as axisartist import mpl_toolkits.axisartist as axisartist
import data as gl_data import data as gl_data
import function # import function
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文不显示问题 mpl.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文不显示问题
plt.rcParams['axes.unicode_minus'] = False #解决负数坐标显示问题 plt.rcParams['axes.unicode_minus'] = False #解决负数坐标显示问题
@ -54,12 +54,30 @@ def selfdata_show(x, y, low, high):# 显示数据集
plt.clf() plt.clf()
set_phtot(1) set_phtot(1)
def fitting(letters,result):
code_str = '''
def func({}):
return {}
'''.format(letters,result)
return code_str
def create_func(code_str):
# 创建一个空的命名空间
namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
exec(code_str, globals(), namespace)
# 返回命名空间中的函数对象
return namespace['func']
def draw_line(xian_index, low, high, sx, sy): def draw_line(xian_index, low, high, sx, sy):
draw_axis(low, high)#绘制坐标轴 draw_axis(low, high)#绘制坐标轴
popt = []#初始化curve_fit popt = []#初始化curve_fit
pcov = []#初始化curve_fit pcov = []#初始化curve_fit
cur = function.Fun[xian_index] # 装载正在选择的函数 letters, result = gl_data.FITT_SAVE['variable'][xian_index], gl_data.FITT_SAVE['function'][xian_index]
func = cur.get_fun()#获取当前函数func code_str = fitting(letters, result)
func = create_func(code_str) # 获取当前函数func
# cur = function.Fun[xian_index] # 装载正在选择的函数
# func = cur.get_fun()#获取当前函数func
popt, pcov = curve_fit(func, sx, sy)# 用curve_fit来对点进行拟合 popt, pcov = curve_fit(func, sx, sy)# 用curve_fit来对点进行拟合
curve_x = np.arange(low, high)#按照步长生成的一串数字 curve_x = np.arange(low, high)#按照步长生成的一串数字
curve_y = [func(i, *popt) for i in curve_x]# 根据x0(按照步长生成的一串数字)来计算y1值 curve_y = [func(i, *popt) for i in curve_x]# 根据x0(按照步长生成的一串数字)来计算y1值
@ -71,20 +89,37 @@ def draw_line(xian_index, low, high, sx, sy):
set_phtot(2)#将图片显示到程序中 set_phtot(2)#将图片显示到程序中
def draw_dots_and_line(xian_index, low, high, sx, sy): def draw_dots_and_line(xian_index, low, high, sx, sy):
if gl_data.Quadrant:
x = sx.tolist()
y = sy.tolist()
negative_x = [i for i, num in enumerate(x) if num < 0]
negative_y = [i for i, num in enumerate(y) if num < 0]
negative = list(set(negative_x + negative_y))
for index in range(len(negative)):
# print(negative[-index-1])
x.pop(negative[-index - 1])
y.pop(negative[-index - 1])
sx = np.array(x)
sy = np.array(y)
print(sx)
############## begin ##################### ############## begin #####################
draw_axis(low, high) draw_axis(low, high)
popt = [] popt = []
pcov = [] pcov = []
cur = function.Fun[xian_index] # 装载正在选择的函数 letters, result = gl_data.FITT_SAVE['variable'][xian_index], gl_data.FITT_SAVE['function'][xian_index]
func = cur.get_fun()#获取当前函数func code_str = fitting(letters, result)
func = create_func(code_str) # 获取当前函数func
print(code_str)
# cur = function.Fun[xian_index] # 装载正在选择的函数
# func = cur.get_fun()#获取当前函数func
popt, pcov = curve_fit(func, sx, sy)# 用curve_fit来对点进行拟合 popt, pcov = curve_fit(func, sx, sy)# 用curve_fit来对点进行拟合
positive_mask = sy >= 0.0#给样本点分类 positive_mask = sy >= 0.0#给样本点分类
negative_mask = sy < 0.0#给样本点分类 negative_mask = sy < 0.0#给样本点分类
positive_colors = ['red' if x >= 0.0 else 'blue' for x in sx]#给样本点分类 positive_colors = ['red' if x >= 0.0 else 'red' for x in sx]#给样本点分类
negative_colors = ['green' if x >= 0.0 else 'purple' for x in sx]#给样本点分类 negative_colors = ['red' if x >= 0.0 else 'red' for x in sx]#给样本点分类
#根据样本点类型决定样本点颜色 #根据样本点类型决定样本点颜色
plt.scatter(gl_data.X[positive_mask], gl_data.Y[positive_mask], color=np.array(positive_colors)[positive_mask], lw=1) plt.scatter(sx[positive_mask], sy[positive_mask], color=np.array(positive_colors)[positive_mask], lw=1)
plt.scatter(gl_data.X[negative_mask], gl_data.Y[negative_mask], color=np.array(negative_colors)[negative_mask], lw=1) plt.scatter(sx[negative_mask], sy[negative_mask], color=np.array(negative_colors)[negative_mask], lw=1)
curve_x = np.arange(low, high)#按照步长生成的一串数字 curve_x = np.arange(low, high)#按照步长生成的一串数字
curve_y = [func(i, *popt) for i in curve_x]# 根据x0(按照步长生成的一串数字)来计算y1值 curve_y = [func(i, *popt) for i in curve_x]# 根据x0(按照步长生成的一串数字)来计算y1值
############## end ####################### ############## end #######################
@ -102,13 +137,17 @@ def set_phtot(index1):
if index1 == 1: if index1 == 1:
gl_data.Img1=PhotoImage(file=r"dot.png") gl_data.Img1=PhotoImage(file=r"dot.png")
# print(gl_data.Img1) # print(gl_data.Img1)
gl_data.Img1 = gl_data.Img1.zoom(2, 2)
set_img1=Canvas2.create_image(2, 10, image=gl_data.Img1, anchor=NW) set_img1=Canvas2.create_image(2, 10, image=gl_data.Img1, anchor=NW)
# Canvas2.itemconfigure(set_img1,int(420 * gl_data.MAGNIDICATION), int(300 * gl_data.MAGNIDICATION))
Canvas2.update() Canvas2.update()
print("已输出数据点") print("已输出数据点")
elif index1 == 2: elif index1 == 2:
gl_data.Img2=PhotoImage(file=r"line.png") gl_data.Img2=PhotoImage(file=r"line.png")
# print(gl_data.Img2) # print(gl_data.Img2)
gl_data.Img2 = gl_data.Img2.zoom(2, 2)
set_img2=Canvas2.create_image(2, 10, image=gl_data.Img2, anchor=NW) set_img2=Canvas2.create_image(2, 10, image=gl_data.Img2, anchor=NW)
# Canvas2.itemconfigure(set_img2, 0,0,int(420*gl_data.MAGNIDICATION), int(300*gl_data.MAGNIDICATION))
Canvas2.update() Canvas2.update()
print("已输出数据点和曲线") print("已输出数据点和曲线")
if __name__ == '__main__': if __name__ == '__main__':

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -6,11 +6,12 @@
@SoftWare: PyCharm @SoftWare: PyCharm
""" """
import tkinter as tk import tkinter as tk
from tkinter import *
import numpy as np import numpy as np
import data as gl_data import data as gl_data
from tkinter import * from fitting import selfdata_show
global top global top
def input_num(root_tk): def input_num(root_tk):
global top global top
@ -31,6 +32,7 @@ def input_data(root_tk, num):
sample_data = [] sample_data = []
top.destroy() top.destroy()
top = tk.Toplevel(root_tk) top = tk.Toplevel(root_tk)
def add_sample_data(): def add_sample_data():
try: try:
x = float(entry_x.get()) x = float(entry_x.get())
@ -40,7 +42,7 @@ def input_data(root_tk, num):
return return
entry_x.delete(0, tk.END) entry_x.delete(0, tk.END)
entry_y.delete(0, tk.END) entry_y.delete(0, tk.END)
if min(x, y) < gl_data.low or max(x, y) > gl_data.high: if min(x, y) < gl_data.LOW or max(x, y) > gl_data.HIGH:
label_status.config(text="输入超过范围") label_status.config(text="输入超过范围")
return return
elif len(sample_data) < num: elif len(sample_data) < num:
@ -53,10 +55,11 @@ def input_data(root_tk, num):
def check_sample_data(): def check_sample_data():
if len(sample_data) == num: if len(sample_data) == num:
label_status.config(text="已达到最大数量") label_status.config(text="已达到最大数量")
gl_data.x = np.array(sample_x) gl_data.X = np.array(sample_x)
gl_data.y = np.array(sample_y) gl_data.Y = np.array(sample_y)
print('已添加', sample_data) print('已添加', sample_data)
top.destroy() top.destroy()
selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH)
else: else:
label_status.config(text="还需输入{}个点对".format(num - len(sample_data))) label_status.config(text="还需输入{}个点对".format(num - len(sample_data)))
print(sample_data) print(sample_data)
@ -77,7 +80,6 @@ def input_data(root_tk, num):
label_status.pack() label_status.pack()
top.mainloop() top.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
root = tk.Tk() root = tk.Tk()
input_num(root) input_num(root)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -0,0 +1,23 @@
import tkinter as tk
from screeninfo import get_monitors
# 创建Tkinter窗口
window = tk.Tk()
window.title("设置按钮尺寸为当前屏幕的百分之85")
window.geometry('190x160')
def jis():
# 获取当前屏幕的宽度和高度
monitors = get_monitors()
screen_width = monitors[0].width
screen_height = monitors[0].height
# 计算按钮的宽度和高度
button_width = int(screen_width * 0.85)
button_height = int(screen_height * 0.85)
# 打印按钮的宽度和高度
print(f"按钮的尺寸:{button_width}x{button_height}")
# 创建一个按钮,并设置尺寸
button = tk.Button(window, text="按钮", command=jis)
button.pack()
# 运行Tkinter事件循环
window.mainloop()

@ -0,0 +1,364 @@
# -*- coding: utf-8 -*-
# Time : 2023/8/9 10:20
# Author : lirunsheng
# User : l'r's
# Software: PyCharm
# File : X5.py
# -*- encoding: utf-8 -*-
"""
@Author: packy945
@FileName: main.py
@DateTime: 2023/5/30 15:29
@SoftWare: PyCharm
"""
import re
from tkinter import messagebox
from PIL import ImageTk, Image
from pandas import DataFrame
import pandas as pd
from sympy import sympify, SympifyError
import sys
from fitting import *
import numpy as np
import data as gl_data
import input
import tkinter as tk
from tkinter import *
import tkinter.filedialog # 注意次数要将文件对话框导入
# from demo1 import Addfunc
from newly_added.formula import expression_output
global Q_root,F_root
global root_window
global label1,label2,label3
from screeninfo import get_monitors
import os
# 创建弹出窗口
def creat_window(title):
top = tk.Toplevel(root_window)
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 check_formula_syntax(formula):
try:
sympify(formula)
return True
except SympifyError:
return False
def create_func(code_str):
# 创建一个空的命名空间
namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
exec(code_str, globals(), namespace)
# 返回命名空间中的函数对象
return namespace['func']
def fitting(letters,result):
code_str = '''
def func({}):
return {}
'''.format(letters,result)
return code_str
def save(result1, letters, result , result2):
gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
gl_data.FITT_SAVE['no'][gl_data.INDEX] = gl_data.INDEX
gl_data.FITT_SAVE['name'][gl_data.INDEX] = result1
gl_data.FITT_SAVE['variable'][gl_data.INDEX] = letters
gl_data.FITT_SAVE['function'][gl_data.INDEX] = result
gl_data.FITT_SAVE['demo'][gl_data.INDEX] = result2
file_path = 'functions_new.xlsx'#设置路径
df = pd.DataFrame(gl_data.FITT_SAVE) # 将字典转换为DataFrame
df.to_excel(file_path, index=False) # 将DataFrame保存为Excel文件
def read_fitting():
file_path = 'functions_new.xlsx' # 设置路径
df = pd.read_excel(io=file_path, header=0) # 设置表格
gl_data.FITT_SAVE = df.to_dict()
def create_func(code_str):
# 创建一个空的命名空间
namespace = {}
# 使用exec函数执行字符串代码并指定命名空间为locals
exec(code_str, globals(), namespace)
# 返回命名空间中的函数对象
return namespace['func']
def addfunc():
top = creat_window('新增拟合函数') # 创建弹出窗口
function_entry = create_input_box(top, "拟合函数名称:", '') # 创建一个输入框,获取拟合函数名称
math_entry = create_input_box(top, "数学式:", '') # 创建一个输入框,获取数学式
def get_input(): # 创建
# 获取输入框的内容
result1 = function_entry.get()
result2 = math_entry.get()
if result1 and result2:
if check_formula_syntax(result2):
top.destroy() # 关闭窗口
letters, result = expression_output(result2)
save(result1, letters, result, result2)
gl_data.Xian_index = gl_data.INDEX
f_button()
else:
messagebox.showinfo('提示', '你输入的数学公式错误!')
else:
messagebox.showinfo('提示','你未输入的完成!')
button = tk.Button(top, text="确定", command=get_input)
button.pack()
def jis():
global screen_size
# 获取当前屏幕的宽度和高度
monitors = get_monitors()
screen_width = monitors[0].width
# 计算按钮的宽度和高度
button_width = int(screen_width * 0.85)
# 打印按钮的宽度和高度
screen_size = round(button_width*0.9/900, 1)
gl_data.MAGNIDICATION = screen_size
read_fitting()
def element(path):
# print(path)
# 加载图像并创建一个 PhotoImage 对象
image = tk.PhotoImage(file=path)
# 保存图片的引用,防止被垃圾回收
root_window.image = image
return image
def window():
global root_window
global label1, label2, label3
root_window = Tk()
root_window.title('函数拟合')
width, height= int(900*screen_size),int(560*screen_size)
root_window.geometry(str(width)+'x'+str(height)) # 设置窗口大小:宽x高,注,此处不能为 "*",必须使用 "x"
# 设置主窗口的背景颜色,颜色值可以是英文单词或者颜色值的16进制数,除此之外还可以使用Tk内置的颜色常量
img_path = ["background/add.png", "background/下方输入框.png", "background/右侧未选中.png", "background/右侧背景.png",
"background/右侧选中.png","background/大背景.png", "background/导航拦.png", "background/导航输入框.png",
"background/小直线.png", "background/手动输入数据集.png", "background/拟合.png", "background/新增拟合曲线类型.png",
"background/显示数据集与曲线.png", "background/未选中.png", "background/生成数据集.png", "background/矩形.png",
"background/背景图片.png", "background/装载.png", "background/选中.png"
]
global list_image
list_image = []
for path in img_path:
list_image.append(element(path))
root_window["background"] = "white"
root_window.resizable(0, 0) # 防止用户调整尺寸
label1 = tk.Label(root_window, text="样本数据\n集文件", font=('Times', 8), bg="white",
width=13, height=3, # 设置标签内容区大小
padx=0, pady=0, borderwidth=0, )
label1.place(x=int(10*screen_size), y=int(4*screen_size)) # 设置填充区距离、边框宽度和其样式(凹陷式)
label3 = tk.Label(root_window, text="", font=('Times', 8), bg="white", fg="black",
width=39, height=2, padx=0, pady=0, borderwidth=0, relief="ridge", highlightcolor="blue")
label3.place(x=int(122*screen_size), y=int(10*screen_size))
# 使用按钮控件调用函数
tk.Button(root_window, image=list_image[17], relief=RAISED, command=lambda: askfile()).place(x=int(370*screen_size), y=int(12*screen_size))
label2 = tk.Label(root_window, text="拟合曲线类型", font=('Times', 12), bg="white",
width=20, height=3, # 设置标签内容区大小
padx=0, pady=0, borderwidth=0, )
# 设置填充区距离、边框宽度和其样式(凹陷式)
label2.place(x=int(450*screen_size), y=int(4*screen_size))
gl_data.Canvas2 = tk.Canvas(root_window, bg='white', width=int(450*screen_size), height=int(330*screen_size))
gl_data.Canvas2.place(x=int(4*screen_size), y=int(60*screen_size))
# 定义一个处理文件的相关函数
def askfile():
# 从本地选择一个文件,并返回文件的路径
filename = tkinter.filedialog.askopenfilename()
if filename != '':#若选中了一个文件,则对文件进行读取
label3.config(text=filename)#显示文件路径
read_sample_data(filename)#将文件读取并存到sampleData中
# print_sample_data(filename)#将文件读取并逐行输出
selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH)
else:#若未选择文件,则显示为空
label3.config(text='')
def print_sample_data(file_path):#打开对应文件
with open(file_path, 'r') as file:
for line in file:#逐行读取文件
line = line.strip('\n')#移除换行符
sx, sy = line.split(' ')#以空格分割xy
print(f'sx: {float(sx)}, sy: {float(sy)}')#将sx、sy转换为浮点数并打印
def read_sample_data(file_path):
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转换为浮点数并加入数组
gl_data.X, gl_data.Y = np.array(x), np.array(y)#xy数组转为array并赋值给全局变量
def buttons():
# 随机生成样本点并显示
b_dot = tk.Button(root_window, text="生成\n数据集", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10),
command=lambda: generate_and_plot_sample_data(gl_data.LOW, gl_data.HIGH))
b_dot.place(x=int(455*screen_size), y=int(410*screen_size))
# 显示当前样本点
b_show = tk.Button(root_window, text="显示\n数据集", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10),
command=lambda: selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH))
b_show.place(x=int(510*screen_size), y=int(410*screen_size))
# 显示数据集与曲线
b_line = tk.Button(root_window, text="显示数据\n集与曲线", relief=RAISED, bd=4, bg="white", font=("微软雅黑", 10),
command=lambda: draw_dots_and_line(gl_data.Xian_index, gl_data.LOW, gl_data.HIGH, gl_data.X, gl_data.Y))
b_line.place(x=int(565*screen_size), y=int(410*screen_size))
# 手动输入数据集
b_input = tk.Button(root_window, text="手动输入数据集", relief=RAISED, bd=4, bg="white", pady=7, font=("微软雅黑", 13),
command=lambda: input.input_num(root_window))
b_input.place(x=int(633*screen_size), y=int(410*screen_size))
# 拟合并输出拟合结果
b_fit = tk.Button(root_window, text="拟合", relief=RAISED, bd=4, bg="white", pady=7, font=("微软雅黑", 13),
command=lambda: fit_data(gl_data.Xian_index, gl_data.X, gl_data.Y))
b_fit.place(x=int(771*screen_size), y=int(410*screen_size))
def show_fit():
L = tk.Label(root_window, text='结果输出:', bg='white', font=("微软雅黑", 16)
, anchor=W)
L.place(x=20, y=int(480*screen_size), width=int(100*screen_size), height=int(30*screen_size))
sout = str(gl_data.Out)
ans = tk.Label(root_window, text=sout, font=("微软雅黑", 14)
, anchor=W, justify='left')
ans.place(x=int(120*screen_size), y=int(480*screen_size), width=int(760*screen_size), height=100)
print(sout)
def fit_data(xian_index, sx, sy):
letters, result = gl_data.FITT_SAVE['variable'][xian_index], gl_data.FITT_SAVE['function'][xian_index]
code_str = fitting(letters, result)
func = create_func(code_str) # 获取当前函数func
popt, pcov = curve_fit(func, sx, sy) # 用curve_fit来对点进行拟合
yvals_pow = func(gl_data.X, *popt)
rr = gl_data.goodness_of_fit(yvals_pow, gl_data.Y)# 计算本次拟合的R*R值用于表示拟合优度
# 输出拟合后的各个参数值
ans = '\n函数系数F(x) = '
letter = str(letters[2:]).split(',')
pattern = re.compile('|'.join(letter))
s = pattern.sub('{:.2f}', gl_data.FITT_SAVE['demo'][xian_index])
ans += str(s.format(*popt))
gl_data.Out = '函数形式:' + gl_data.FITT_SAVE['name'][xian_index] + ' '
gl_data.Out += gl_data.FITT_SAVE['demo'][xian_index]
gl_data.Out += ans
gl_data.Out += '\n拟合优度(R\u00b2)' + str(round(rr, 5))
show_fit()# 显示函数信息到输出框
def change_Q(no):
gl_data.Quadrant = no #更改全局变量的象限显示
if no:#若为一象限则修改显示下限为0
gl_data.LOW = 0
else:#若为四象限,则修改显示下限为-gl_data.maxV
gl_data.LOW = -gl_data.MAXV
q_button()#更新象限显示面板
def q_button():
r = 7.5
rr = 2.5
for widget in Q_root.winfo_children():
widget.destroy()
q_cv = tk.Canvas(Q_root, width=int(400*screen_size), height=int(50*screen_size))
q_cv.place(x=0, y=0)
l = tk.Label(Q_root, text='坐标轴', bd=0, font=("微软雅黑", 16)
, anchor=W)
l.place(x=20, y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 四象限按钮
b1 = tk.Button(Q_root, text='四象限', bd=0, font=("微软雅黑", 16)
, command=lambda: change_Q(0), anchor=W)
b1.place(x=int(170*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 一象限按钮
b2 = tk.Button(Q_root, text='一象限', bd=0, font=("微软雅黑", 16)
, command=lambda: change_Q(1), anchor=W)
b2.place(x=int(320*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
# 绘制标记框
q_cv.create_oval(int((140 - r)*screen_size), int((25 - r)*screen_size), int((140 + r)*screen_size), int((25 + r)*screen_size)
, fill="white", width=1, outline="black")
q_cv.create_oval(int((290 - r)*screen_size), int((25 - r)*screen_size), int((290 + r)*screen_size), int((25 + r)*screen_size)
, fill="white", width=1, outline="black")
# 根据当前的象限选择值来填充标记框
if gl_data.Quadrant == 0:
q_cv.create_oval(int((140 - rr)*screen_size), int((25 - rr)*screen_size), int((140 + rr)*screen_size), int((25 + rr)*screen_size)
, fill="black", width=1, outline="black")
else:
q_cv.create_oval(int((290 - rr)*screen_size), int((25 - rr)*screen_size), int((290 + rr)*screen_size), int((25 + rr)*screen_size)
, fill="black", width=1, outline="black")
def change_f(no):
gl_data.Xian_index = no#设置全局函数编号为该函数
f_button()#重新绘制函数显示界面
def f_button():
r = 7.5 # 设置按钮大小
rr = 2.5 # 设置按钮大小
for widget in F_root.winfo_children():
widget.destroy() # 清空原有按钮
gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
# 创建滚动条
scrollbar = tk.Scrollbar(F_root)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 创建Canvas对象
f_cv = tk.Canvas(F_root, width=int(370 * screen_size), height=int(310 * screen_size), yscrollcommand=scrollbar.set)
f_cv.pack(side=tk.LEFT)
# 设置滚动条与Canvas的关联
scrollbar.config(command=f_cv.yview)
# # 绘制矩形边框及底色
# f_cv.create_rectangle(2, 2, int(398 * screen_size), int(328 * screen_size), fill='white',
# outline="#0099ff")
cur = 0 # 函数计数
for i in range(gl_data.INDEX): # 遍历函数库
f_cv.create_oval(int((20 - r) * screen_size), int((20 + 15 + cur * 30 - r) * screen_size),
int((20 + r) * screen_size), int((20 + 15 + cur * 30 + r) * screen_size)
, fill="white", width=1, outline="black") # 绘制标记框
if gl_data.FITT_SAVE['no'][i] == gl_data.Xian_index: # 若选择为当前函数则标记
f_cv.create_oval(int((20 - rr) * screen_size), int((20 + 15 + cur * 30 - rr) * screen_size),
int((20 + rr) * screen_size), int((20 + 15 + cur * 30 + rr) * screen_size)
, fill="black", width=int(screen_size), outline="black")
# 绘制切换按钮,单击则将当前使用函数切换为该函数
button = tk.Button(F_root, text=gl_data.FITT_SAVE['name'][i] + ' ' + gl_data.FITT_SAVE['demo'][i], bd=0,
bg="white", font=("微软雅黑", 12),
command=lambda x=gl_data.FITT_SAVE['no'][i]: change_f(x), anchor=W)
# 将按钮放置在Canvas中
f_cv.create_window(int(40 * screen_size), int((35 + cur * 30) * screen_size), window=button, anchor="w")
cur += 1 # 计数加一
f_cv.configure(scrollregion=f_cv.bbox("all"))
def close_window():
sys.exit()
def main():
global Q_root, F_root,root_window
jis()
# gl_data.LOW, gl_data.HIGH = int(gl_data.LOW*screen_size), int(gl_data.HIGH*screen_size)
gl_data.X = []
gl_data.X = []
window()
# 函数选择相关界面
F_root = tk.Frame(root_window, width=int(400*screen_size), height=int(330*screen_size), bg='white', )
F_root.place(x=int(490*screen_size), y=int(60*screen_size))
# 象限选择相关界面
Q_root = tk.Frame(root_window, width=int(400*screen_size), height=int(50*screen_size), bg='white', )
Q_root.place(x=int(20*screen_size), y=int(410*screen_size))
buttons()
f_button()
q_button()
show_fit()
tk.Button(root_window, text="新增拟合曲线类型", bd=4, command=addfunc).place(x=int(740*screen_size), y=int(12)*screen_size)
# 设置Grid布局的列和行权重
root_window.protocol("WM_DELETE_WINDOW", close_window)
root_window.mainloop()
if __name__ == '__main__':
main()
pass

@ -0,0 +1,70 @@
# import re
#
# def add_spaces(expression):
# # 匹配运算符的正则表达式
# pattern = r'([+\-*/])'
# # 替换匹配到的运算符
# new_expression = re.sub(pattern, r' \1 ', expression)
# return new_expression
#
# # 示例用法
# expression = 'a+b^c-c*d/e'
# new_expression = add_spaces(expression)
# print(new_expression)
import re
from formula import *
def remove_inner_spaces(expression):
# 匹配括号内的空格的正则表达式
pattern = r'\((.*?)\)'
# 替换匹配到的括号内的空格
new_expression = re.sub(pattern, lambda match: '(' + match.group(1).replace(' ', '') + ')', expression)
return new_expression
def add_spaces(expression):
# 匹配运算符的正则表达式
pattern = r'([+\-*/])'
# 替换匹配到的运算符
new_expression = re.sub(pattern, r' \1 ', expression)
return new_expression
# 示例用法
expression = 'a+b^c-c*d/e+sin(x+y)+e^(0.2*x)'
expression = add_spaces(expression)
new_expression = remove_inner_spaces(expression)
list_expression = new_expression.split(' ')
conforms = ['e^', 'log', 'sin', 'cos', 'tan', '^']
new_list = []
# result2 = ' '.join([word for word in expression.split() if not any(word.startswith(s) for s in conforms)])
# print(result2)
# letters = [char for char in result2 if char.isalpha()]
# print(letters)
for expres in list_expression:
new_list.append(expres)
for i in range(6):
if conforms[i] in expres:
index = list_expression.index(expres)
if i == 0:
list_expression[index] = convert_e(expres)
elif i==1:
list_expression[index] = convert_log(expres)
elif i==5:
list_expression[index] = convert_x(expres)
else:
list_expression[index] = convert_trigonometric(expres)
new_list[-1] = new_list[-1].replace(conforms[i], "")
break
new_list = [char for item in new_list for char in item if char.isalpha()]
parameter =''
for item in new_list:
if item not in parameter:
parameter = parameter+item+','
print(parameter[:-1])
for item in new_list:
if item not in parameter:
parameter = parameter+item+','
str_expression = ''
for item in list_expression:
str_expression = str_expression + item
print(str_expression[:-1])
print(list_expression)

@ -0,0 +1,44 @@
import mpl_toolkits.axisartist as axisartist
from scipy.optimize import curve_fit
from pandas import DataFrame
import matplotlib.pyplot as plt
import numpy as np
import pylab as mpl
from tkinter import *
import data as gl_data
import pandas as pd
import tkinter
import sys
import tkinter as tk
from tkinter import filedialog
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 解决matplotlib中文不显示问题
plt.rcParams['axes.unicode_minus'] = False # 解决matplotlib负数坐标显示问题
# 创建一个二维数组sampleData用于存储样本数据
sampleData = []
def askfile():# 从本地选择一个文件,并返回文件的路径
global sampleData
# 弹出文件选择对话框,选择要打开的文本文件
file_path = filedialog.askopenfilename(filetypes=[('Text Files', '*.txt')])
# 如果没有选择文件,直接返回
if not file_path:
return
# 步骤1打开样本数据集文件并读取每行数据
with open(file_path, 'r') as file:
lines = file.readlines()
# 步骤2遍历所有行将每行数据解析为sx和sy值转换为浮点数并存储到sampleData中
for line in lines:
sx, sy = line.strip().split(' ')
sx = float(sx)
sy = float(sy)
sampleData.append([sx, sy])
# # 步骤3使用循环遍历样本数据并打印出来
# for data in sampleData:
# print(data)
if __name__ == '__main__':
askfile()

@ -0,0 +1,19 @@
import re
def find_letter_index(string):
pattern = r'([a-zA-Z])x\b'
matches = re.findall(pattern, string)
letter_indices = []
for match in matches:
letter_index = string.index(match)
letter_indices.append(letter_index)
return letter_indices
# 示例使用
string = "ax+b + cx - dx + e^x"
indices = find_letter_index(string)
print(indices)

@ -0,0 +1,4 @@
screen_size = 1.8
r = 7.5
rr = 2.5
print(int((20 - rr) * screen_size))

@ -0,0 +1,41 @@
import numpy as np
from scipy.optimize import leastsq
import matplotlib.pyplot as plt
# 定义待拟合的函数形式
def func(x, coeffs):
return coeffs[0] * np.sin(coeffs[1] * x) + coeffs[2]
# 定义目标函数,即待拟合数据
def target_func(x):
return 2.5 * np.sin(0.7 * x) + 1.2
# 生成带噪声的待拟合数据
np.random.seed(0)
x_data = np.linspace(-10, 10, 100)
y_data = target_func(x_data) + np.random.normal(0, 0.5, 100)
# 定义误差函数,即最小二乘法的目标函数
def residuals(coeffs, y, x):
return y - func(x, coeffs)
# 初始参数的估计值
initial_coeffs = [1, 1, 1]
# 使用最小二乘法拟合函数
result = leastsq(residuals, initial_coeffs, args=(y_data, x_data))
best_coeffs = result[0]
# 打印拟合得到的系数
print("拟合得到的系数:", best_coeffs)
# 绘制拟合结果
x_fit = np.linspace(-10, 10, 100)
y_fit = func(x_fit, best_coeffs)
plt.plot(x_data, y_data, 'bo', label='原始数据')
plt.plot(x_fit, y_fit, 'r-', label='拟合曲线')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

@ -0,0 +1,51 @@
import numpy as np
import matplotlib.pyplot as plt
# 定义待拟合的函数形式
def func(x, coeffs):
return coeffs[0] * x + coeffs[1]
# 定义目标函数,即待拟合数据
def target_func(x):
return 2.5 * x + 1.2
# 生成带噪声的待拟合数据
np.random.seed(0)
x_data = np.linspace(0, 10, 100)
y_data = target_func(x_data) + np.random.normal(0, 0.5, 100)
# 定义损失函数,即拟合函数与目标函数之间的差距
def loss_func(coeffs, x, y):
return np.mean((y - func(x, coeffs))**2)
# 定义梯度计算函数,即损失函数对于系数的偏导数
def gradient_func(coeffs, x, y):
gradient = np.zeros_like(coeffs)
gradient[0] = -2 * np.mean((y - func(x, coeffs)) * x)
gradient[1] = -2 * np.mean(y - func(x, coeffs))
return gradient
# 初始化参数
learning_rate = 0.01
num_iterations = 1000
initial_coeffs = np.array([1.0, 1.0], dtype=float)
# 使用梯度下降法拟合函数
coeffs = initial_coeffs
for i in range(num_iterations):
gradient = gradient_func(coeffs, x_data, y_data)
coeffs -= learning_rate * gradient
# 打印拟合得到的系数
print("拟合得到的系数:", coeffs)
# 绘制拟合结果
x_fit = np.linspace(0, 10, 100)
y_fit = func(x_fit, coeffs)
plt.plot(x_data, y_data, 'bo', label='原始数据')
plt.plot(x_fit, y_fit, 'r-', label='拟合曲线')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

@ -0,0 +1,51 @@
# def make_func(letters,result):
# global func_x
# # print(letters,result)
# draw_axis(-100, 100, 20)
# letter = str(letters).split(',')
# n = len(letter)-1
# decimals = [round(random.uniform(-10, 10), 1) for _ in range(n)]
# target_result = functional_formula(letter[1:],result,decimals)
# # output.configure(state="normal")
# # output.delete("1.0", tk.END) # 删除当前输出框中的所有文本
# # output.insert(tk.END, target_result)
# # output.configure(state="disabled")
# code_str = fitting('x', target_result)
# # print(code_str)
# target_func = create_func(code_str) # 获取当前函数func
# # # print(target_result)
# # # 生成带噪声的待拟合数据
# # np.random.seed(0)
# # x_data = np.linspace(-100, 100, 50)
# # y_data = target_func(x_data) + np.random.normal(0, 0.5, 50)
# # # print(y_data)
# # code_str = fitting(letters, result)
# # print(code_str)
# # func_x = create_func(code_str) # 获取当前函数func
# #
# # # 初始参数的估计值
# # initial_coeffs = [1.0 for _ in range(n)]
# # # 使用最小二乘法拟合函数
# # result = leastsq(residuals, initial_coeffs, args=(y_data, x_data))
# # best_coeffs = result[0]
# # # 打印拟合得到的系数
# # print("拟合得到的系数:", best_coeffs)
#
# # 绘制拟合结果
# x_fit = np.linspace(-100, 100, 50)
# y_fit = target_func(x_fit)
#
# # plt.plot(x_data, y_data, 'bo', label='原始数据')
# plt.plot(x_fit, y_fit, 'r-', label='拟合曲线')
# plt.legend()
# plt.xlabel('x')
# plt.ylabel('y')
# # plt.show()
# plt.savefig('new_line.png')
# # 清除当前图形状态
# plt.clf()
# show_image()
#
# # 定义误差函数,即最小二乘法的目标函数
# def residuals(coeffs, y, x):
# return y - func_x(x, *coeffs)

@ -0,0 +1,17 @@
from sympy import symbols, Eq, simplify
x = symbols('x')
a = symbols('a')
b = symbols('b')
expr1 = a*x + b
expr2 = 12*x + 1.3
eq = Eq(expr1, expr2) # 创建一个等式表达式
simplified_eq = simplify(eq) # 化简等式
if simplified_eq == True:
print("两个表达式相等")
else:
print("两个表达式不相等")

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -0,0 +1,103 @@
import re
def convert_log(expression):
# 匹配log(x,b)的正则表达式
pattern = r'log\((\w+),(\w+)\)'
match = re.match(pattern, expression)
if match:
x = match.group(1)
b = match.group(2)
# 构造新表达式
new_expression = f'(np.log({x}) + 1e-5) / (np.log({b}) + 1e-5)'
return new_expression
else:
return None
def convert_e(expression):
new_expression = 'np.exp'+expression[2:]
return new_expression
def convert_trigonometric(expression):
# 构造新表达式
new_expression = 'np.'+expression
return new_expression
def convert_x(expression):
# 匹配log(x,b)的正则表达式
pattern = r'(\w+)\^(\w+)'
match = re.match(pattern, expression)
if match:
base = match.group(1)
exponent = match.group(2)
# 构造新表达式
new_expression = f'np.power({base}, {exponent})'
return new_expression
else:
return None
def remove_inner_spaces(expression):
# 匹配括号内的空格的正则表达式
pattern = r'\((.*?)\)'
# 替换匹配到的括号内的空格
new_expression = re.sub(pattern, lambda match: '(' + match.group(1).replace(' ', '') + ')', expression)
return new_expression
def add_spaces(expression):
# 匹配运算符的正则表达式
pattern = r'([+\-*/])'
# 替换匹配到的运算符
new_expression = re.sub(pattern, r' \1 ', expression)
return new_expression
def find_letter_index(string):
pattern = r'([a-zA-Z])x\b'
matches = re.findall(pattern, string)
# print(matches)
letter_indices = []
for i in range(len(string)):
if string[i] in matches:
if string[i+1]=='x':
letter_indices.append(i)
return letter_indices
def expression_output(expression):
# 示例使用
modified_list = find_letter_index(expression) # 将x前没有*的加上
index = 1
for i in modified_list:
expression = expression[0:index+i]+'*'+expression[index+i:]
index += 1
# print(expression)
expression = add_spaces(expression)
new_expression = remove_inner_spaces(expression)
list_expression = new_expression.split(' ')
conforms = ['e^', 'log', 'sin', 'cos', 'tan', '^']
new_list = []
for expres in list_expression:
new_list.append(expres)
for i in range(6):
if conforms[i] in expres:
index = list_expression.index(expres)
if i == 0:
list_expression[index] = convert_e(expres)
elif i == 1:
list_expression[index] = convert_log(expres)
elif i == 5:
list_expression[index] = convert_x(expres)
else:
list_expression[index] = convert_trigonometric(expres)
new_list[-1] = new_list[-1].replace(conforms[i], "")
break
new_list = [char for item in new_list for char in item if char.isalpha()]
parameter ='x,'
for item in new_list:
if item not in parameter and item != 'x':
parameter = parameter+item+','
for item in new_list:
if item not in parameter:
parameter = parameter+item+','
str_expression = ''
for item in list_expression:
str_expression = str_expression + item
if len(parameter[:-1]) > 1:
return parameter[:-1], str_expression
else:
return None, None

@ -0,0 +1,144 @@
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()
Loading…
Cancel
Save