|
|
|
|
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 pandas as pd
|
|
|
|
|
import tkinter
|
|
|
|
|
import sys
|
|
|
|
|
import tkinter as tk
|
|
|
|
|
from tkinter import filedialog
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import function
|
|
|
|
|
import data as gl_data
|
|
|
|
|
from X1 import *
|
|
|
|
|
from X2 import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 解决matplotlib中文不显示问题
|
|
|
|
|
plt.rcParams['axes.unicode_minus'] = False # 解决matplotlib负数坐标显示问题
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 创建一个二维数组sampleData,用于存储样本数据
|
|
|
|
|
sampleData = None
|
|
|
|
|
|
|
|
|
|
global Q_root,F_root
|
|
|
|
|
global root_window
|
|
|
|
|
global label1,label2,label3
|
|
|
|
|
|
|
|
|
|
# 编程4.6 -----------------------------------------
|
|
|
|
|
|
|
|
|
|
# 定义一个处理文件的相关函数
|
|
|
|
|
def askfile():
|
|
|
|
|
# 选择需要加载的数据文件,并返回文件的路径
|
|
|
|
|
filename = tkinter.filedialog.askopenfilename()
|
|
|
|
|
if filename != '': # 若选中了一个文件,则对文件进行读取
|
|
|
|
|
label3.config(text=filename) # 显示文件路径,其中label3为对应的按钮
|
|
|
|
|
read_sample_data(filename) # 将文件读取并存到sampleData中
|
|
|
|
|
# print_sample_data(filename)# 将文件读取并逐行输出
|
|
|
|
|
selfdata_show(gl_data.SampleData[:,0], gl_data.SampleData[:,1], 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(' ') # 以空格分割x,y
|
|
|
|
|
print(f'sx: {float(sx)}, sy: {float(sy)}') # 将sx、sy转换为浮点数并打印
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read_sample_data(file_path):
|
|
|
|
|
x, y = [], [] # 初始化x,y
|
|
|
|
|
with open(file_path, 'r') as file:
|
|
|
|
|
for line in file: # 逐行读文件
|
|
|
|
|
line = line.strip('\n') # 移除换行符
|
|
|
|
|
sx, sy = line.split(' ') # 以空格分割x,y
|
|
|
|
|
x.append(float(sx)) # 将sx转换为浮点数并加入数组
|
|
|
|
|
y.append(float(sy)) # 将sy转换为浮点数并加入数组
|
|
|
|
|
# x,y数组转为array并赋值给全局变量sampleData
|
|
|
|
|
x = np.array(x) # 列表转数组
|
|
|
|
|
y = np.array(y)
|
|
|
|
|
gl_data.SampleData = np.array(list(zip(x, y)))
|
|
|
|
|
|
|
|
|
|
# 编程4.6 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 编程4.7 -----------------------------------------
|
|
|
|
|
def generate_and_plot_sample_data(sampleData, Low, High):
|
|
|
|
|
sx,sy = sampleData[:, 0],sampleData[:, 1]
|
|
|
|
|
draw_axis(Low, High) # 绘制坐标轴
|
|
|
|
|
plt.scatter(sx, sy, color='red') # 绘制样本数据点
|
|
|
|
|
plt.savefig(r"dot.png", facecolor='w', bbox_inches='tight') # 保存到本地
|
|
|
|
|
plt.close() # 清除内存
|
|
|
|
|
set_phtot(1) # 显示到主界面 4.7示例时没有编程该函数
|
|
|
|
|
# if __name__ == '__main__':
|
|
|
|
|
# num_samples = 25 #设置样本点数量
|
|
|
|
|
# sampleData = random_points(num_samples, -1000, 1000) # 生成随机样本数据25个
|
|
|
|
|
# generate_and_plot_sample_data(sampleData, gl_data.LOW, gl_data.HIGH)
|
|
|
|
|
|
|
|
|
|
# 编程4.7 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
# 编程4.8 -----------------------------------------
|
|
|
|
|
def draw_dots_and_line(curveData, sampleData, low, high):
|
|
|
|
|
x_fit, y_fit = curveData[:, 0], curveData[:, 1]
|
|
|
|
|
x, y = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
|
|
|
|
|
draw_axis(low, high) # 画xy坐标轴
|
|
|
|
|
positive_mask = y >= 0.0 # 给样本点分类
|
|
|
|
|
negative_mask = y < 0.0 # 给样本点分类
|
|
|
|
|
positive_colors = ['red' if xx >= 0.0 else 'blue' for xx in x] # 给样本点分类
|
|
|
|
|
negative_colors = ['green' if xx >= 0.0 else 'purple' for xx in x] # 给样本点分类
|
|
|
|
|
# 创建图形对象并绘制拟合曲线和样本点
|
|
|
|
|
ax = draw_axis(low,high,step=250)
|
|
|
|
|
# 根据样本点类型决定样本点颜色
|
|
|
|
|
ax.scatter(x[positive_mask], y[positive_mask], color=np.array(positive_colors)[positive_mask], lw=1)
|
|
|
|
|
ax.scatter(x[negative_mask], y[negative_mask], color=np.array(negative_colors)[negative_mask], lw=1)
|
|
|
|
|
|
|
|
|
|
plt.plot(x_fit, y_fit, color='blue', label='Fitted Curve')# 绘制拟合曲线
|
|
|
|
|
# plt.savefig(r"dot5.png", facecolor='w') # 保存到本地
|
|
|
|
|
# plt.legend()
|
|
|
|
|
# plt.show()
|
|
|
|
|
|
|
|
|
|
# X5修改后展示到主界面中
|
|
|
|
|
plt.legend(loc='center left', bbox_to_anchor=(1, 0.9), fontsize=9)
|
|
|
|
|
plt.savefig(r"line.png", facecolor='w', bbox_inches='tight')# 将图片保存到本地
|
|
|
|
|
plt.close()# 清除内存
|
|
|
|
|
set_phtot(2)# 将图片显示到程序中
|
|
|
|
|
|
|
|
|
|
# if __name__ == '__main__':
|
|
|
|
|
# gl_data.SampleData = random_points(25,-1000, 1000)
|
|
|
|
|
# # print("gl_data.SampleData",gl_data.SampleData)
|
|
|
|
|
# draw_dots_and_line(gl_data.LOW, gl_data.HIGH, gl_data.SampleData)
|
|
|
|
|
|
|
|
|
|
# if __name__ == '__main__':
|
|
|
|
|
# LimitNum = 1000
|
|
|
|
|
# # sampleData = random_points(20,0, 1000)
|
|
|
|
|
# # x, y = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
# # 这里为了便于观察使用设计好的数据
|
|
|
|
|
# x = np.array([0, 100, 200, 300, 400, 500, 600, 700, 800, 900])
|
|
|
|
|
# y = np.array([10, 20, 10, 50, 80, 130, 210, 340, 550, 890])
|
|
|
|
|
# sampleData = np.array(list(zip(x, y))) # 将两个一维数组拼接成二维数组
|
|
|
|
|
# m = 3 # 使用三次函数拟合
|
|
|
|
|
# theta, covariance_matrix = least_square_method(m, sampleData)
|
|
|
|
|
# curveData = compute_curveData2(0,1000,1,theta,m, x.mean(), x.std())
|
|
|
|
|
# draw_dots_and_line(curveData,sampleData,0,1000)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 编程4.8 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
# 编程4.9 -----------------------------------------
|
|
|
|
|
|
|
|
|
|
def input_num(root_tk):
|
|
|
|
|
global top
|
|
|
|
|
top = tk.Toplevel(root_tk)
|
|
|
|
|
top.geometry("300x50")
|
|
|
|
|
top.title('坐标点个数')
|
|
|
|
|
label1 = Label(top, text="坐标点个数")
|
|
|
|
|
label1.grid(row=0) # 这里的side可以赋值为LEFT RTGHT TOP BOTTOM
|
|
|
|
|
num1 = IntVar()
|
|
|
|
|
entry1 = Entry(top, textvariable=num1)
|
|
|
|
|
num1.set(0)
|
|
|
|
|
entry1.grid(row=0, column=1)
|
|
|
|
|
Label(top, text=" ").grid(row=0, column=3)
|
|
|
|
|
Button(top, text="确定", command=lambda: input_data(root_tk, int(entry1.get()))).grid(row=0, column=3)
|
|
|
|
|
top.mainloop()
|
|
|
|
|
|
|
|
|
|
def add_sample_data():
|
|
|
|
|
global sample_x, sample_y, sample_data
|
|
|
|
|
global entry_x,entry_y,label_status, numx
|
|
|
|
|
try:
|
|
|
|
|
x = float(entry_x.get())
|
|
|
|
|
y = float(entry_y.get())
|
|
|
|
|
except:
|
|
|
|
|
label_status.config(text="输入不合法")
|
|
|
|
|
return
|
|
|
|
|
entry_x.delete(0, tk.END)
|
|
|
|
|
entry_y.delete(0, tk.END)
|
|
|
|
|
if min(x, y) < gl_data.LOW or max(x, y) > gl_data.HIGH:
|
|
|
|
|
label_status.config(text="输入超过范围")
|
|
|
|
|
return
|
|
|
|
|
elif len(sample_data) < numx:
|
|
|
|
|
label_status.config(text="点对已添加")
|
|
|
|
|
sample_data.append((x, y))
|
|
|
|
|
sample_x.append(x)
|
|
|
|
|
sample_y.append(y)
|
|
|
|
|
else:
|
|
|
|
|
label_status.config(text="已达到最大数量")
|
|
|
|
|
|
|
|
|
|
def check_sample_data():
|
|
|
|
|
global label_status,numx,sample_x,sample_y,sample_data
|
|
|
|
|
if len(sample_data) == numx:
|
|
|
|
|
label_status.config(text="已达到最大数量")
|
|
|
|
|
gl_data.X = np.array(sample_x)
|
|
|
|
|
gl_data.Y = np.array(sample_y)
|
|
|
|
|
print('已添加', sample_data)
|
|
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
label_status.config(text="还需输入{}个点对".format(numx - len(sample_data)))
|
|
|
|
|
print(sample_data)
|
|
|
|
|
|
|
|
|
|
def input_data(root_tk, num):
|
|
|
|
|
global top
|
|
|
|
|
global sample_x,sample_y,sample_data
|
|
|
|
|
global numx
|
|
|
|
|
numx = num
|
|
|
|
|
sample_x = []
|
|
|
|
|
sample_y = []
|
|
|
|
|
sample_data = []
|
|
|
|
|
top.destroy()
|
|
|
|
|
top = tk.Toplevel(root_tk)
|
|
|
|
|
top.geometry("300x200")
|
|
|
|
|
top.title('坐标')
|
|
|
|
|
global entry_x, entry_y, label_status
|
|
|
|
|
label_x = tk.Label(top, text="X 值:")
|
|
|
|
|
label_x.pack()
|
|
|
|
|
entry_x = tk.Entry(top)
|
|
|
|
|
entry_x.pack()
|
|
|
|
|
label_y = tk.Label(top, text="Y 值:")
|
|
|
|
|
label_y.pack()
|
|
|
|
|
entry_y = tk.Entry(top)
|
|
|
|
|
entry_y.pack()
|
|
|
|
|
button_add = tk.Button(top, text="添加", command=add_sample_data)
|
|
|
|
|
button_add.pack()
|
|
|
|
|
button_check = tk.Button(top, text="检查", command=check_sample_data)
|
|
|
|
|
button_check.pack()
|
|
|
|
|
label_status = tk.Label(top, text="")
|
|
|
|
|
label_status.pack()
|
|
|
|
|
top.mainloop()
|
|
|
|
|
# 编程4.9 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 编程4.10 -----------------------------------------
|
|
|
|
|
def error_func(func, sampleData, theta): # 定义误差函数
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
y_pred = func(theta, sx) # 使用func函数和参数theta计算预测值
|
|
|
|
|
error = np.sum((sy - y_pred) ** 2) # 计算误差平方和
|
|
|
|
|
ss_tot = np.sum((sy - np.mean(sy)) ** 2) # 计算总平方和
|
|
|
|
|
r_squared = 1 - (error / ss_tot) # 计算决定系数(R^2)
|
|
|
|
|
return error, r_squared
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 这里是处理了标准化的error_func
|
|
|
|
|
def error_func2(func, sampleData, theta): # 定义误差函数
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
x_normalized = (sx - sx.mean()) / sx.std()
|
|
|
|
|
# 使用func函数和参数theta计算预测值
|
|
|
|
|
y_pred = func(theta, x_normalized)
|
|
|
|
|
# 计算误差平方和
|
|
|
|
|
error = np.sum((sy - y_pred) ** 2)
|
|
|
|
|
# 计算总平方和
|
|
|
|
|
ss_tot = np.sum((sy - np.mean(sy)) ** 2)
|
|
|
|
|
# 计算决定系数(R^2)
|
|
|
|
|
r_squared = 1 - (error / ss_tot)
|
|
|
|
|
return error, r_squared
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# fit函数中修改使用方法为梯度下降法,并输出拟合结果
|
|
|
|
|
def fit(sampleData, m):
|
|
|
|
|
|
|
|
|
|
theta, covariance_matrix = least_square_method(m, sampleData) # 计算拟合结果
|
|
|
|
|
# 计算拟合误差
|
|
|
|
|
if m == 1: func = linear_function
|
|
|
|
|
if m == 2: func = quadratic_function # 此处以m=2为例,省略其他函数
|
|
|
|
|
if m == 3: func = qubic_function
|
|
|
|
|
if m == 4: func = quartic_function
|
|
|
|
|
error,r_squared = error_func2(func, sampleData, theta)
|
|
|
|
|
fit_function_name = func.__name__ # 打印拟合函数的形式、系数、误差和优度
|
|
|
|
|
print("拟合函数形式:{}".format(fit_function_name))
|
|
|
|
|
print("标准化拟合系数:{}".format(theta))
|
|
|
|
|
print("误差:{:.4f}".format(error))
|
|
|
|
|
print("拟合优度(R^2):{:.4f}".format(r_squared))
|
|
|
|
|
return theta, covariance_matrix
|
|
|
|
|
# if __name__ == '__main__':
|
|
|
|
|
# # sampleData = random_points(20,0, 1000)
|
|
|
|
|
# # x = sampleData[:,0]
|
|
|
|
|
# # y = sampleData[:,1]
|
|
|
|
|
# # 这里为了便于观察使用设计好的数据
|
|
|
|
|
# x = np.array([0, 100, 200, 300, 400, 500, 600, 700, 800, 900])
|
|
|
|
|
# y = np.array([10, 20, 10, 50, 80, 130, 210, 340, 550, 890])
|
|
|
|
|
# sampleData = np.array(list(zip(x, y))) # 将两个一维数组拼接成二维数组
|
|
|
|
|
# m = 2 # 假设选择使用二次函数拟合
|
|
|
|
|
# theta, covariance_matrix = fit(sampleData, m)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ------fit_X4前提函数-------
|
|
|
|
|
# 为了适应扩展的函数,需要根据用户输入的函数类型构造函数
|
|
|
|
|
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']
|
|
|
|
|
|
|
|
|
|
# 简化版本的goodness_of_fit
|
|
|
|
|
def goodness_of_fit_easy(y_fitting, y_no_fitting):
|
|
|
|
|
"""
|
|
|
|
|
计算拟合优度R^2
|
|
|
|
|
:param y_fitting: List[int] or array[int] 拟合好的y值
|
|
|
|
|
:param y_no_fitting: List[int] or array[int] 待拟合y值
|
|
|
|
|
:return: 拟合优度R^2
|
|
|
|
|
"""
|
|
|
|
|
y_mean = sum(y_no_fitting) / len(y_no_fitting)
|
|
|
|
|
# 计算SST
|
|
|
|
|
sst = sum((y - y_mean) ** 2 for y in y_no_fitting)
|
|
|
|
|
# 计算SSE
|
|
|
|
|
sse = sum((y_fitting[i] - y_no_fitting[i]) ** 2 for i in range(len(y_fitting)))
|
|
|
|
|
# 计算R^2
|
|
|
|
|
r_squared = 1 - sse / sst
|
|
|
|
|
return r_squared
|
|
|
|
|
# ------fit_X4前提函数-------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 这里是为了后续的fit能够直接用到按钮中,而不是BF_Fit写一大堆
|
|
|
|
|
def fit_X4(xian_index, sampleData):
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
|
|
|
|
|
cur = function.Fun[xian_index] # 装载正在选择的函数
|
|
|
|
|
func = cur.get_fun() # 获取当前函数func
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
popt, pcov = gradient_descent_method_X5(func, sx, sy) # 用curve_fit来对数据进行拟合
|
|
|
|
|
|
|
|
|
|
x_normalized = (sx - np.mean(sx)) / np.std(sx) # 标准化处理的x
|
|
|
|
|
y_pred = func(x_normalized, *popt) # 获取y的预测值
|
|
|
|
|
|
|
|
|
|
gl_data.CurveData = compute_curveData_X5_2(func, popt, sampleData) # 计算拟合曲线的数据
|
|
|
|
|
rr = goodness_of_fit_easy(y_pred, sy) # 计算本次拟合的R*R值,用于表示拟合优度
|
|
|
|
|
|
|
|
|
|
# 输出拟合后的各个参数值
|
|
|
|
|
ans = '\n函数标准化系数:F(x) = '
|
|
|
|
|
for i in range(cur.variable):
|
|
|
|
|
if i == 4:
|
|
|
|
|
ans += '\n'
|
|
|
|
|
if i != 0:
|
|
|
|
|
ans += ', '
|
|
|
|
|
ans += chr(ord('a') + i) + '=' + '{:.2e}'.format(popt[i]) # str(round(gl_data.popt[i], 3))
|
|
|
|
|
gl_data.Out = '函数形式:' + cur.name + ' '
|
|
|
|
|
gl_data.Out += cur.demo
|
|
|
|
|
gl_data.Out += ans
|
|
|
|
|
gl_data.Out += '\n拟合优度(R\u00b2):' + str(round(rr, 5))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 编程4.17-----------------------------------------
|
|
|
|
|
# 选择
|
|
|
|
|
def fit_X4(xian_index, sampleData):
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
|
|
|
|
|
cur = function.Fun[xian_index] # 装载正在选择的函数
|
|
|
|
|
func = cur.get_fun() # 获取当前函数func
|
|
|
|
|
|
|
|
|
|
# params_count = func.__code__.co_argcount - 2 # 计算参数数量
|
|
|
|
|
# if params_count <= 3 and len(sampleData) <= 20 : # 当参数和样本点数量较少时
|
|
|
|
|
# popt, pcov = least_square_method(func, sx, sy) # 用最小二乘法来对数据进行拟合
|
|
|
|
|
# else: # 当参数和样本点数量较多时
|
|
|
|
|
# popt, pcov = gradient_descent_method_X5(func, sx, sy) # 用梯度下降法来对数据进行拟合
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
popt, pcov = gradient_descent_method_X5(func, sx, sy)
|
|
|
|
|
|
|
|
|
|
x_normalized = (sx - np.mean(sx)) / np.std(sx) # 标准化处理的x
|
|
|
|
|
y_pred = func(x_normalized, *popt) # 获取y的预测值
|
|
|
|
|
|
|
|
|
|
gl_data.CurveData = compute_curveData_X5_2(func, popt, sampleData) # 计算拟合曲线的数据
|
|
|
|
|
rr = goodness_of_fit_easy(y_pred, sy) # 计算本次拟合的R*R值,用于表示拟合优度
|
|
|
|
|
|
|
|
|
|
# 输出拟合后的各个参数值
|
|
|
|
|
ans = '\n函数标准化系数:F(x) = '
|
|
|
|
|
for i in range(cur.variable):
|
|
|
|
|
if i == 4:
|
|
|
|
|
ans += '\n'
|
|
|
|
|
if i != 0:
|
|
|
|
|
ans += ', '
|
|
|
|
|
ans += chr(ord('a') + i) + '=' + '{:.2e}'.format(popt[i])
|
|
|
|
|
gl_data.Out = '函数形式:' + cur.name + ' '
|
|
|
|
|
gl_data.Out += cur.demo
|
|
|
|
|
gl_data.Out += ans
|
|
|
|
|
gl_data.Out += '\n拟合优度(R\u00b2):' + str(round(rr, 5))
|
|
|
|
|
# 编程4.17 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
# 这里是为了后续的fit能够直接用到按钮中,而不是BF_Fit写一大堆
|
|
|
|
|
def fit_X5(xian_index, sampleData):
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
|
|
|
|
|
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 = gradient_descent_method_X5(func, sx, sy) # 用curve_fit来对数据进行拟合
|
|
|
|
|
|
|
|
|
|
x_normalized = (sx - np.mean(sx)) / np.std(sx)
|
|
|
|
|
y_pred = func(x_normalized, *popt) # 获取y的预测值
|
|
|
|
|
|
|
|
|
|
gl_data.CurveData = compute_curveData_X5_2(func, popt, sampleData) # 计算拟合曲线的数据
|
|
|
|
|
rr = goodness_of_fit_easy(y_pred, sy) # 计算本次拟合的R*R值,用于表示拟合优度
|
|
|
|
|
|
|
|
|
|
# 输出拟合后的各个参数值
|
|
|
|
|
ans = '\n函数系数:F(x) = '
|
|
|
|
|
letter = str(letters[2:]).split(',')
|
|
|
|
|
pattern = re.compile('|'.join(letter))
|
|
|
|
|
s = pattern.sub('{:.2g}', gl_data.FITT_SAVE['demo'][xian_index])
|
|
|
|
|
print(pattern)
|
|
|
|
|
print(gl_data.FITT_SAVE['demo'][xian_index])
|
|
|
|
|
print("s:", s)
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 这里是使用curve_fit实现的,实际使用的方式
|
|
|
|
|
def fit_XX(xian_index, sampleData):
|
|
|
|
|
sx, sy = sampleData[:, 0], sampleData[:, 1]
|
|
|
|
|
|
|
|
|
|
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来对数据进行拟合
|
|
|
|
|
y_pred = func(sx, *popt) # 获取y的预测值
|
|
|
|
|
|
|
|
|
|
gl_data.CurveData = compute_curveData_X5(func, popt) # 计算拟合曲线的数据
|
|
|
|
|
rr = goodness_of_fit_easy(y_pred, sy) # 计算本次拟合的R*R值,用于表示拟合优度
|
|
|
|
|
|
|
|
|
|
# 输出拟合后的各个参数值
|
|
|
|
|
ans = '\n函数系数:F(x) = '
|
|
|
|
|
letter = str(letters[2:]).split(',')
|
|
|
|
|
pattern = re.compile('|'.join(letter))
|
|
|
|
|
s = pattern.sub('{:.2g}', gl_data.FITT_SAVE['demo'][xian_index])
|
|
|
|
|
print(pattern)
|
|
|
|
|
print(gl_data.FITT_SAVE['demo'][xian_index])
|
|
|
|
|
print("s:", s)
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
# 编程4.10 END-----------------------------------------
|
|
|
|
|
|
|
|
|
|
# 编程4.11 -----------------------------------------
|
|
|
|
|
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_X3() #更新象限显示面板
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def q_button_X3():
|
|
|
|
|
r = 7.5
|
|
|
|
|
rr = 2.5
|
|
|
|
|
for widget in Q_root.winfo_children():
|
|
|
|
|
widget.destroy()
|
|
|
|
|
q_cv = tk.Canvas(Q_root, width=450, height=500)
|
|
|
|
|
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=80, height=50,)
|
|
|
|
|
# 四象限按钮
|
|
|
|
|
b1 = tk.Button(Q_root, text='四象限', bd=0, font=("微软雅黑", 16)
|
|
|
|
|
, command=lambda: change_Q(0), anchor=W)
|
|
|
|
|
b1.place(x=170, y=0, width=80, height=50,)
|
|
|
|
|
# 一象限按钮
|
|
|
|
|
b2 = tk.Button(Q_root, text='一象限', bd=0, font=("微软雅黑", 16)
|
|
|
|
|
, command=lambda: change_Q(1), anchor=W)
|
|
|
|
|
b2.place(x=320, y=0, width=80, height=50,)
|
|
|
|
|
# 绘制标记框
|
|
|
|
|
q_cv.create_oval(140 - r, 25 - r, 140 + r, 25 + r, fill="white", width=1, outline="black")
|
|
|
|
|
q_cv.create_oval(290 - r, 25 - r, 290 + r, 25 + r , fill="white", width=1, outline="black")
|
|
|
|
|
# 根据当前的象限选择值来填充标记框
|
|
|
|
|
if gl_data.Quadrant == 0:
|
|
|
|
|
q_cv.create_oval(140 - rr, 25 - rr, 140 + rr, 25 + rr, fill="black", width=1, outline="black")# 绘制象限
|
|
|
|
|
else:
|
|
|
|
|
q_cv.create_oval(290 - rr, 25 - rr, 290 + rr, 25 + rr, fill="black", width=1, outline="black")
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
# 象限选择相关界面
|
|
|
|
|
Q_root = tk.Tk()
|
|
|
|
|
Q_root.geometry("500x550") # 设置窗口的大小和位置
|
|
|
|
|
q_button_X3()
|
|
|
|
|
Q_root.mainloop()
|
|
|
|
|
|
|
|
|
|
# 编程4.11 END-----------------------------------------
|