gpt4 book ai didi

python - 如何通过回调更新 PyQt 中的散点图?

转载 作者:行者123 更新时间:2023-12-01 00:54:07 25 4
gpt4 key购买 nike

我有这个程序,当用户单击按钮时,我想用用户给出的新数据更新先前绘制的图。我想做的是向用户展示分类器系统的决策边界图,当用户添加新数据时,我想相应地更新我的散点图。这是我的代码:

from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg,
FigureManagerQT,
)
from PyQt5 import QtWidgets
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
class CustomFigureCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, cmap_name="coolwarm"):
fig = Figure()
self.color_map = plt.get_cmap(cmap_name)
self.axes = fig.add_subplot(111)
super().__init__(fig)
self.setParent(parent)
self.setBaseSize(300, 300)
self.setMaximumSize(400, 400)
self.setMinimumSize(250, 250)
self.setSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding,
)

def set_clf_2d(self, clf_2d):
self.clf = clf_2d

def plot_new_datapoints(self, x2D):
self.add_datapoint(x2D)

@staticmethod
def _make_meshgrid(x, y, h=0.02):
x_min, x_max = x.min() - 1, x.max() + 1
y_min, y_max = y.min() - 1, y.max() + 1
XX, YY = np.meshgrid(
np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)
)
return XX, YY

def _plot_contours(self, xx, yy, **params):
"""Plot the decision boundaries for a classifier.

Parameters
----------
ax: matplotlib axes object
clf: a classifier
xx: meshgrid ndarray
yy: meshgrid ndarray
params: dictionary of params to pass to contourf, optional
"""
Z = self.clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
self.axes.contourf(xx, yy, Z, **params)

def plot_data(self, x2D, y):
"""plots the given array and the decision function bounday.

Arguments:
x2D {np.array} -- [2d array]
y {np.array} -- [1d array]
"""

x0, x1 = x2D[:, 0], x2D[:, 1]
xx, yy = CustomFigureCanvas._make_meshgrid(x0, x1)
labels = ["Cognitive", "Not Cognitive"]
colors = ["r", "b"]
self.axes.clear()
self._plot_contours(xx, yy, cmap=self.color_map, alpha=0.8)
target_ids = [0, 1]

for i, c, label in zip(target_ids, colors, labels):
print(i, label)
self.axes.scatter(
x0[y == i],
x1[y == i],
color=c,
label=label,
marker="o",
s=(15, 15),
)

self.axes.set_xlim(xx.min(), xx.max())
self.axes.set_ylim(yy.min(), yy.max())
self.axes.set_title("2D Representation using PCA")
self.axes.legend(fontsize=8)
self.axes.plot()

def add_datapoint(self, x2d):
"""Adds a new datapoint to the plot

Arguments:
x2d {a 2d single point, [x,y]} -- [np.array with shape (1,2)]
axes {plt.axes} -- [description]

"""
print(x2d, type(x2d))
self.axes.scatter(
x2d[:, 0],
x2d[:, 1],
color="k",
label="Current Text",
marker="o",
s=(15, 15),
)
self.axes.legend(fontsize=8)
self.axes.plot()

我当前遇到的问题是,在调用_plot_contours之后,绘图将不会更新。在阅读了 matplotlib 中的“可更新”图形后,我看到一些建议使用 plt.ion() 来生成可更新的图形。还有一些关于使用 FuncAnimation 类的建议,但这并不完全是我需要的解决方案,因为它不依赖于用户的按钮单击回调,而是在给定的时间间隔内刷新绘图。

编辑:这是重现我遇到的问题的最小代码:

import sys
from PyQt5 import QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import (
NavigationToolbar2QT as NavigationToolbar,
)
from matplotlib.figure import Figure
from custom_figure_canvas import CustomFigureCanvas

import random
import numpy as np
from sklearn.svm import SVC


class Window(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)

# a figure instance to plot on
self.figure = Figure()

# this is the Canvas Widget that displays the `figure`
# it takes the `figure` instance as a parameter to __init__
self.canvas = CustomFigureCanvas(parent=self)

# this is the Navigation widget
# it takes the Canvas widget and a parent
self.toolbar = NavigationToolbar(self.canvas, self)

# Just some button connected to `plot` method
self.button = QtWidgets.QPushButton("Plot")
self.button.clicked.connect(self.plot)

# set the layout
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button)
self.setLayout(layout)

def plot(self):

x2D = np.random.rand(50, 2)
y = np.random.randint(0, 2, size=(50,))

x2D_train = np.random.rand(50, 2)
y_train = np.random.randint(0, 2, size=(50,))

clf = SVC()
clf.fit(x2D_train, y_train)

print(x2D)
self.canvas.set_clf_2d(clf)
self.canvas.plot_data(x2D, y)


if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)

main = Window()
main.show()

sys.exit(app.exec_())

最佳答案

对于使用 Qt 的 matplotlib,您必须刷新绘图,为此您可以使用以下方法:

self.axes.figure.canvas.draw_idle()

或者

self.axes.figure.canvas.draw()

就您而言:

# ...

def _plot_contours(self, xx, yy, **params):
# ...
self.axes.contourf(xx, yy, Z, **params)
self.axes.figure.canvas.draw()

def plot_data(self, x2D, y):
# ...
self.axes.plot()
self.axes.figure.canvas.draw()

# ...

输出:

enter image description here

关于python - 如何通过回调更新 PyQt 中的散点图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56347501/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com