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

277 lines
13 KiB
Python

2 years ago
# -*- coding: utf-8 -*-
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QFileDialog, QColorDialog
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
from matplotlib.path import Path
from matplotlib.patches import Patch
from PySide6.QtGui import QPalette
import random
# plt.legend(prop={'family': 'SimHei', 'size': 15})
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.toolbar = None
self.canvas = None
self.file_paths = []
self.get_color = lambda n: list(map(lambda i: "#" + "%06x" % random.randint(0, 0xFFFFFF),range(n)))
self.color = self.get_color(100) # 图例颜色选择值
self.colorbar = 'jet'
self.num = len(self.color) # 记录选择颜色的次数
self.oilwell_color = 'k'
self.waterwell_color = 'k'
self.chose = 0
self.num = 0
# 加载UI文件
self.ui = QUiLoader().load('QT/main_2.ui')
self.color_bar()
self.ui.legend_color.clicked.connect(self.legend_color_chose) # 选择图例颜色
self.ui.colorbar_chose.currentTextChanged.connect(self.update_colorbar) # 更新colorbar
self.ui.chose_oilwell_color.clicked.connect(lambda: self.oil_well_color()) # 选择油井颜色
self.ui.chose_oilwell_color.clicked.connect(lambda: self.plot_density()) # 更新油井颜色
self.ui.chose_waterwell_color.clicked.connect(lambda: self.water_well_color()) # 选择水井颜色
self.ui.chose_waterwell_color.clicked.connect(lambda: self.plot_density()) # 更新水井颜色
# 更新图窗
self.ui.graphicsView.repaint()
self.ui.graphicsView.update()
self.graphics_layout = QVBoxLayout(self.ui.graphicsView)
self.ui.chose_datafile_button.clicked.connect(self.choose_datafile)
self.ui.chose_wellfile_button.clicked.connect(self.choose_wellfile)
# 绘制或清除数据和画布
self.ui.clear_data.clicked.connect(lambda: self.clear_data())
# 绘图设置中心比例
self.ui.center_scale.clicked.connect(lambda: self.center_scale())
self.ui.center_scale.clicked.connect(lambda: self.plot_density())
self.ui.level_chose.valueChanged.connect(lambda: self.plot_density())
self.ui.gWeight_chose.valueChanged.connect(lambda: self.plot_density())
def self_levels(self):
self.levels = self.ui.level_chose.value() # 选择层参数
self.plot_density()
def self_gWeight(self):
self.gWeight = self.self.ui.gWeight_chose.value()
self.plot_density()
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()
def choose_datafile(self):
file_dialog = QFileDialog(self)
file_dialog.setFileMode(QFileDialog.ExistingFiles)
if file_dialog.exec():
self.file_paths += file_dialog.selectedFiles()
self.ui.data_file_lineEdit.setText(','.join(self.file_paths))
self.plot_density()
def choose_wellfile(self):
file_dialog = QFileDialog(self)
file_dialog.setFileMode(QFileDialog.ExistingFiles)
if file_dialog.exec():
file_paths = file_dialog.selectedFiles()
self.ui.well_file_lineEdit.setText(','.join(file_paths))
self.plot_density()
def legend_color_chose(self):
col = QColorDialog.getColor()
self.color[self.num] = col.name()
self.num += 1
self.plot_density()
def oil_well_color(self):
col = QColorDialog.getColor()
self.oilwell_color = col.name()
def water_well_color(self):
col = QColorDialog.getColor()
self.waterwell_color = col.name()
def color_bar(self):
self.ui.colorbar_chose.addItem("jet")
self.ui.colorbar_chose.addItem("viridis")
self.ui.colorbar_chose.addItem("coolwarm")
self.ui.colorbar_chose.addItem('plasma')
self.ui.colorbar_chose.addItem("magma")
self.ui.colorbar_chose.addItem("inferno")
def update_colorbar(self):
colorbar_name = self.ui.colorbar_chose.currentText()
self.colorbar = plt.get_cmap(colorbar_name)
self.plot_density()
def clear_data(self):
self.file_paths = []
self.color = self.get_color(100)
self.num = 0
self.ui.data_file_lineEdit.clear()
self.ui.well_file_lineEdit.clear()
self.canvas.figure.clf() # 清除画布上的内容
self.canvas.draw()
def center_scale(self):
if self.chose == 0:
self.chose = 1
else:
self.chose = 0
self.num = 0
def plot_density(self):
fig, ax = self.scene_fig()
data_name = self.ui.data_file_lineEdit.text().split(',') # 文件输入 =================1
level_nums = self.ui.level_chose.value() # 层参数 =================2
gWeight = self.ui.gWeight_chose.value() # 权重输入 =================3
data = CREAT.create()
legend_elements = []
if self.num == len(data_name):
self.num = 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]
# 填充等高线图中间的区域
if len(data_name) > 1:
color_i = self.color[i] # """ 自动选择图例的颜色""" =================4
level = [levels[0], levels[-1]]
ff = ax.contourf(xx, yy, f, levels=level, colors=color_i, alpha=1, zorder=len(data_name) - i)
# 生成图例
legend_elements.append(Patch(facecolor=color_i, label=''+f'{i+1}'+''))
if i == len(data_name)-1:
ax.legend(handles=legend_elements, loc='upper right', prop={'family': 'SimHei', 'size': 10})
# ax.legend(prop={'family': 'SimHei', 'size': 15})
else:
# colorbars = 'jet' # 输入选择的colorbar =================5
cmap = mpl.colormaps.get_cmap(self.colorbar)
colors = cmap(np.linspace(0, 1, level_nums))
ff = ax.contourf(xx, yy, f, levels=levels, colors=colors[0:level_nums], alpha=0.5,
zorder=len(data_name) - i)
# 生成colorbar
sm = mpl.cm.ScalarMappable(cmap=cmap, norm=mpl.colors.Normalize(vmin=ff.zmin, vmax=ff.zmax))
sm.set_array([])
fig.colorbar(sm, ax=ax)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Density Distribution')
wells_name = self.ui.well_file_lineEdit.text() # 井文件输入 =================6
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
x_len = ((np.array(points)[:, 0].max()-np.array(points)[:,0].min())//100+2)*100
y_len = ((np.array(points)[:, 1].max()-np.array(points)[:,1].min())//100+2)*100
if self.chose == 1:
max_x = max(np.array([(np.array(points)[:, 0].max()//100+1)*100, (np.array(points)[:, 1].max()//100+1)*100, data.x_range[1], data.y_range[1]]))
min_x = max(np.array([(np.array(points)[:, 0].min()//100-1)*100, (np.array(points)[:, 1].min()//100-1)*100, data.x_range[0], data.y_range[0]]))
max_x = max(max_x, -min_x)
ax.set_xlim([-max_x, max_x])
ax.set_ylim([-max_x, max_x])
x_len = max(x_len, y_len)
y_len = x_len
for i in range(len(points)):
is_inside = False # 标记点是否在等高线内部
# path = Path(contours_p)
# if path.contains_point(points[i]):
if np.linalg.norm(contours_p[i]) >= np.linalg.norm(points[i]):
is_inside = True
if typee[i][0] == 0:
# oil_color = 'black' # 输入油井颜色选择 =================8
ax.scatter(points[i][0], points[i][1], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=70)
ax.scatter(points[i][0], points[i][1], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=40,
linewidths=0.5)
ax.scatter(points[i][0], points[i][1], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=20)
if wells.angle[i] <= 90:
ax.text(points[i][0] - 1/35*x_len, points[i][1] - 1/30*y_len, f'{namee[i][0]}',
fontdict={'size': '8', 'color': 'b'}) # 井名信息
elif wells.angle[i] > 270:
ax.text(points[i][0] + 3/175*x_len, points[i][1] - 1/40*y_len, f'{namee[i][0]}',
fontdict={'size': '8', 'color': 'b'}) # 井名信息
else:
ax.text(points[i][0] - 3/80*x_len, points[i][1] + 3/175*y_len, f'{namee[i][0]}',
fontdict={'size': '8', 'color': 'b'}) # 井名信息
if not is_inside:
# 绘制油井边缘最短距离点的箭头并标出距离
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) # 绘制箭头
if np.linalg.norm(np.array(points[i])-np.array(contours_p[i])) > 50:
ax.text(points[i][0] * 1 / 2 + contours_p[i][0] * 1 / 2 + min_distance[i] / 18,
points[i][1] * 1 / 2 + contours_p[i][1] * 1 / 2 - min_distance[i] / 18,
f'{round(min_distance[i], 2)}m',
fontdict={'size': '8', 'color': 'm'}) # 标出距离
else:
if wells.angle[i] <= 90:
ax.text(points[i][0]-3/70*x_len, points[i][1]+1/40*y_len, f'{round(min_distance[i], 2)}m',
fontdict={'size': '8', 'color': 'm'}) # 标出距离
elif wells.angle[i] > 270:
ax.text(points[i][0] - 1/35*x_len, points[i][1] + 1/30*y_len, f'{round(min_distance[i], 2)}m',
fontdict={'size': '8', 'color': 'm'}) # 标出距离
else:
ax.text(points[i][0] + 3/140*x_len, points[i][1] - 1/40*y_len, f'{round(min_distance[i], 2)}m',
fontdict={'size': '8', 'color': 'm'}) # 标出距离
else:
# water_color = 'black' # 水井颜色 =================9
ax.scatter(points[i][0], points[i][1], marker='o', edgecolors=self.waterwell_color, facecolors=self.waterwell_color, s=70, zorder=len(data_name)+1)
ax.text(points[i][0] + 15, points[i][1] - 15, f'{namee[i][0]}',
fontdict={'size': '8', 'color': 'b'}, zorder=len(data_name) + 2) # 井名信息
continue
self.canvas_adjust(fig)
if __name__ == '__main__':
app = QApplication([])
stats = MainWindow()
stats.ui.show()
app.exec()