commit 1e3fb0bc6c1e52d62d62f038e3744b406a89eac5 Author: 冯冬卫 Date: Sun Apr 2 10:40:52 2023 +0800 代码提交 diff --git a/CREAT.py b/CREAT.py new file mode 100644 index 0000000..3bc7706 --- /dev/null +++ b/CREAT.py @@ -0,0 +1,134 @@ +import numpy as np +import matplotlib as mpl +import matplotlib.pyplot as plt +from scipy.stats import gaussian_kde +from scipy.spatial.distance import cdist +import copy + + +class create(): + def __init__(self): + """ + data is the x and y coordinate of data.pos + contours is the edge points + f is the kernel density value + levels is the levels for contours + x_range is the range of x label + y_range is the range of y label + + """ + self.data = [] + self.contours = [] + self.f = [] + self.levels = [] + self.x_range = [] + self.y_range = [] + + def data_pre(self, data_name): + with open(data_name, 'r') as f: + lines = f.readlines() + L_en=len(lines) + lines= lines[1:L_en] + data = [] + for line in lines: + x, y,z,t = line.strip().split("\t") + data.append(list(map(float, [x,y]))) + data = np.array(data) + self.data = data + self.x_range = [min(data[:, 0]), max(data[:,0])] + self.y_range = [min(data[:, 1]), max(data[:,1])] + + def contours_pre(self, level_nums, gWeight): + + x = self.data[:, 0] + y = self.data[:, 1] + # 使用scipy库中的gaussian_kde函数计算密度估计 + kde = gaussian_kde(self.data.T) + # 生成网格点坐标 + xx, yy = np.mgrid[x.min():x.max():200j, y.min():y.max():200j] + positions = np.vstack([xx.ravel(), yy.ravel()]) + # 计算网格点上的密度估计值 + f = np.reshape(kde(positions).T, xx.shape) + # 绘制等高线图 + levels = [] + for i in range(level_nums): + levels.append(f.max() - (level_nums - i - 1) * (f.max() - f.min()) / gWeight) + self.levels = levels + contours = plt.contour(xx, yy, f, levels=[levels[0], levels[level_nums - 1]], cmap='coolwarm', alpha=0) + plt.close() + self_contours = [] + for i in range(len(contours.allsegs[0])): + self_contours += contours.allsegs[0][i].tolist() + + for i in range(len(self_contours)): + if self_contours[i] not in self.contours: + self.contours += [self_contours[i]] + + self.f = f + + +class well_to_edge(): + def __init__(self): + """ + name is used to store the well names + type is the types of the wells + position is the coordinates of wells + min_distance is the minimum distances between wells and edge + welltoedge_points is the points responding to the min_distance + angle is the angles between the shortest distance direction vector from the well to the edge and the positive direction of the y-axis during clockwise rotation; + wells_num: the number of wells + """ + self.name = [] + self.type = [] + self.position = [] + self.min_distance = [] + self.welltoedge_points = [] + self.angle = [] + self.wells_num = 0 + + def wells_name_and_position(self, wells_name): + # 读取井位信息 + with open(wells_name, 'r') as f_j: + j_ing = f_j.readlines() + points = [] + typee = [] + namee = [] + for line in j_ing: + x, y, type, name = line.strip().split("\t") + points.append(list(map(float, [x, y]))) + typee.append(list(map(int, [type]))) + namee.append(name.split('\n')) + self.position = points + self.name = namee + self.type = typee + self.wells_num = len(points) + + def welltoedge_distance(self, contour_points): + min_distance = [] + contours_p=[] + angles=[] + wells_num = self.wells_num + points = self.position + # 定义待计算距离的点 + for i in range(wells_num): + point = np.array([points[i][0], points[i][1]]) + # 计算点到等高线上所有点之间的距离 + distances = cdist(point.reshape(1, -1), contour_points) + # 取距离的最小值 + min_distance.append(distances.min()) + # 记录最短距离对应的点 + for ii in range(distances.size): + if distances[0][ii] == min_distance[-1]: + contours_p.append(contour_points[ii]) + # 计算角度(y轴为正北方向) + direct = contours_p[-1] - point + if direct[0] < 0: + angles.append(360-np.arccos(np.dot(direct, np.array(([0, 1]))) / np.linalg.norm( + direct)) / np.pi * 180) + else: + angles.append(np.arccos(np.dot(direct, np.array(([0, 1]))) / np.linalg.norm( + direct)) / np.pi * 180) + + self.min_distance = min_distance + self.welltoedge_points = contours_p + self.angle = angles \ No newline at end of file diff --git a/test2.py b/test2.py new file mode 100644 index 0000000..5db7a46 --- /dev/null +++ b/test2.py @@ -0,0 +1,131 @@ +import sys +from PySide6.QtWidgets import QApplication, QMainWindow, QGraphicsView +from PySide6.QtUiTools import QUiLoader +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar +from matplotlib.figure import Figure +import matplotlib.pyplot as plt +from PySide6.QtWidgets import QVBoxLayout +import CREAT +import numpy as np +import matplotlib as mpl + + +class MainWindow(QMainWindow): + def __init__(self): + super().__init__() + self.toolbar = None + self.canvas = None + # 加载UI文件 + self.ui = QUiLoader().load('QT/PLT2.ui') + # 更新图窗 + self.ui.graphicsView.repaint() + self.ui.graphicsView.update() + self.graphics_layout = QVBoxLayout(self.ui.graphicsView) + # 绘制Matplotlib图形 + self.ui.pushButton_4.clicked.connect(lambda: self.plot_density()) + + def plot_density(self): + fig, ax = self.scene_fig() + data_name = self.ui.lineEdit.text().split(',') + level_nums = self.ui.spinBox_2.value() + gWeight = self.ui.spinBox.value() + data = CREAT.create() + zmin = 1 + zmax = 0 + for i in range(len(data_name)): + data.data_pre(data_name[i]) + data.contours_pre(level_nums, gWeight) + + """画出密度等高线""" + f = data.f + x_min, x_max = data.x_range[0], data.x_range[1] + y_min, y_max = data.y_range[0], data.y_range[1] + levels = data.levels + + xx, yy = np.mgrid[x_min:x_max:200j, y_min:y_max:200j] + # 填充等高线图中间的区域 + cmap = mpl.colormaps.get_cmap('jet') + colors = cmap(np.linspace(0, 1, level_nums)) + level = [levels[0], levels[-1]] + ff = ax.contourf(xx, yy, f, levels=level, colors=colors[level_nums - i - 1:level_nums - i], alpha=1, + zorder=len(data_name) - i) + zmin = min(zmin, ff.zmin) + zmax = max(zmax, ff.zmax) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_title('Density Distribution') + + # 生成colorbar + sm = mpl.cm.ScalarMappable(cmap=cmap, norm=mpl.colors.Normalize(vmin=zmin, vmax=zmax)) + sm.set_array([]) + fig.colorbar(sm, ax=ax) + + wells_name = self.ui.lineEdit_4.text() + if wells_name == '': + self.canvas_adjust(fig) + else: + wells = CREAT.well_to_edge() + wells.wells_name_and_position(wells_name) + wells.welltoedge_distance(data.contours) + + """画井位信息""" + typee = wells.type + points = wells.position + namee = wells.name + min_distance = wells.min_distance + contours_p = wells.welltoedge_points + for i in range(len(points)): + if typee[i][0] == 0: + ax.scatter(points[i][0], points[i][1], marker='o', edgecolors='black', facecolors='none', s=100) + ax.scatter(points[i][0], points[i][1], marker='o', edgecolors='black', facecolors='none', s=50, + linewidths=1) + ax.scatter(points[i][0], points[i][1], marker='o', edgecolors='black', facecolors='none', s=30) + ax.text(points[i][0] + min_distance[i] / 20, points[i][1] - min_distance[i] / 20, f'{namee[i][0]}', + fontdict={'size': '10', 'color': 'b'}, zorder=len(data_name) + 2) # 井名信息 + else: + + ax.scatter(points[i][0], points[i][1], marker='o', edgecolors='black', facecolors='black', s=100, zorder=len(data_name)+1) + ax.text(points[i][0] + min_distance[i] / 20, points[i][1] - min_distance[i] / 20, f'{namee[i][0]}', + fontdict={'size': '10', 'color': 'b'}, zorder=len(data_name) + 2) # 井名信息 + continue + # 绘制油井边缘最短距离点的箭头并标出距离 + ax.quiver(points[i][0], points[i][1], contours_p[i][0] - points[i][0], contours_p[i][1] - points[i][1], + angles='xy', scale=1.03, + scale_units='xy', width=0.002, zorder=len(data_name)+1) # 绘制箭头 + ax.text(points[i][0] * 1 / 9 + contours_p[i][0] * 8 / 9 + min_distance[i] / 20, + points[i][1] * 1 / 9 + contours_p[i][1] * 8 / 9 - min_distance[i] / 20, f'{round(min_distance[i], 2)}', + fontdict={'size': '10', 'color': 'g'}) # 标出距离 + ax.text(points[i][0] * 1 / 2 + contours_p[i][0] * 1 / 2 + min_distance[i] / 20, + points[i][1] * 1 / 2 + contours_p[i][1] * 1 / 2 - min_distance[i] / 20, + r'$\theta$=' f'{round(wells.angle[i], 2)}', fontdict={'size': '10', 'color': 'y'}) # 标出角度 + self.canvas_adjust(fig) + + def scene_fig(self): + fig = Figure() + # 在Figure对象中添加子图 + ax = fig.add_subplot(111) + return fig, ax + + def canvas_adjust(self, fig): + if self.canvas is not None: + # 从布局中删除旧的 canvas 和 toolbar + item = self.graphics_layout.takeAt(0) + while item: + widget = item.widget() + if widget: + widget.setParent(None) + item = self.graphics_layout.takeAt(0) + self.graphics_layout.removeWidget(self.canvas) + self.canvas = FigureCanvas(fig) + self.toolbar = NavigationToolbar(self.canvas, self.ui.graphicsView) + self.toolbar.setParent(self.canvas) + self.graphics_layout.addWidget(self.canvas) + self.adjustSize() + + +if __name__ == '__main__': + app = QApplication([]) + stats = MainWindow() + stats.ui.show() + app.exec()