当使用大数据集(10k)按下PyQt5按钮时,会变得极不负责任

2024-04-20 14:07:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试开发一个小型的数据采集GUI,如下所示,所有功能都可以用于小型数据集。这就是它的工作原理:单击“开始/停止”启动或停止轨迹图以及直方图的更新。轨迹使用python生成器从2个txt文件中获取数据,每个文件包含1000 000个点。再次按下相同的按钮后,它将停止更新。就这样。问题是,当接近系统上的10000点时,性能开始迅速衰减。但是,性能的下降仅仅取决于系统对按下按钮的反应,曲线图一直在更新,因为它什么都没有。这怎么可能?我该怎么解决呢?下面我将发布一些可能有助于捕获错误的代码(我将省略布局内容)

很抱歉发了这么长的邮件。 enter image description here

def read_file(file):
    for row in open(file, "r"):
        yield row

    while True:
        yield None


def gaussian(x, B, mu, sigma):
    return B * np.exp(-1.0 * (x - mu) ** 2 / (2 * sigma ** 2))


class Ui_MainWindow(object):
    counter = 0
    XDATA = read_file("xdata.txt")
    YDATA = read_file("ydata.txt")

    def setupUi(self, MainWindow):
        (...)

        self.map = pg.PlotWidget(self.centralwidget)
        (...)

        self.yhist = pg.PlotWidget(self.centralwidget)
        (...)
        self.xhist = pg.PlotWidget(self.centralwidget)
        (...)
        # Connect buttons to slots
        self.start_stop.clicked.connect(self.start)
        self.clear.clicked.connect(self.clear_data)
        self.fitButton.clicked.connect(self.fit)

        # Plot dummy data to map
        self.xdata = [0]
        self.ydata = [0]
        self.curve = pg.PlotDataItem(self.xdata, self.ydata)
        self.map.addItem(self.curve)

        # plot dummy data to xhist
        self.freqx, self.binsx = np.histogram(self.xdata)
        self.binscenters_x = np.array([0.5 * (self.binsx[i] + self.binsx[i + 1]) for i in range(len(self.binsx) - 1)])
        self.freqx = self.freqx / np.max(self.freqx)

        self.x_bar = pg.BarGraphItem(x=self.binscenters_x, height=self.freqx,
                                     width=self.binsx[2] - self.binsx[3],
                                     brush='r')

        pen = pg.mkPen(color=(255, 255, 0), width=2.5, style=QtCore.Qt.SolidLine)
        self.fitLine_x = pg.PlotDataItem([0], [0], pen=pen)
        self.xhist.addItem(self.x_bar)
        self.xhist.addItem(self.fitLine_x)

        # plot dummy data to yhist
        self.freqy, self.binsy = np.histogram(self.xdata)
        self.binscenters_y = np.array([0.5 * (self.binsy[i] + self.binsy[i + 1]) for i in range(len(self.binsy) - 1)])
        self.freqx = self.freqx / np.max(self.freqx)

        self.y_bar = pg.BarGraphItem(x=self.binscenters_y, height=self.freqy,
                                     width=self.binsx[2] - self.binsx[3],
                                     brush='r')
        self.fitLine_y = pg.PlotDataItem([0], [0], pen=pen)
        self.yhist.addItem(self.y_bar)
        self.yhist.addItem(self.fitLine_y)

        # Set a timer for the update
        # make QTimer
        self.qTimer = QtCore.QTimer()
        # set interval
        self.qTimer.setInterval(5)  # 1000 ms = 1 s
        # connect timeout signal to signal handler
        self.qTimer.timeout.connect(self.update)

    def start(self):
        start=0
        end=0
        current_counts=0
        if self.start_stop.isChecked():
            print("start")
            start=time()
            current_counts = self.counter
            self.qTimer.start()
            self.fitButton.setEnabled(False)
            self.clear.setEnabled(False)
        else:
            print("stop")
            self.qTimer.stop()
            self.fitButton.setEnabled(True)
            self.clear.setEnabled(True)
            end = time()
            print(end)
            print("FPS: ", (self.counter-current_counts) / (end - start))
            print("Total number of points read: ", self.counter)

    def clear_data(self):
        self.xdata = [0]
        self.ydata = [0]
        self.curve.setData(self.xdata, self.ydata)

    def fit(self):
        params_x, cov_x = curve_fit(gaussian, self.binscenters_x, self.freqx)
        params_y, cov_y = curve_fit(gaussian, self.binscenters_y, self.freqy)

        # plot it on the histograms
        data_range = np.linspace(-1, 1, 1000)

        self.fitLine_x.setData(data_range, gaussian(data_range, *params_x))
        self.fitLine_y.setData(data_range, gaussian(data_range, *params_y))

        # print the data to the tables
        (...)

    def update(self):
        # print(self.counter)
        self.counter += 1

        # update map
        if next(self.XDATA) is None:
            pass
        else:
            self.xdata.append(float(next(self.XDATA)))
            self.ydata.append(float(next(self.YDATA)))
            self.curve.setData(self.xdata, self.ydata)


            # update xhist
            self.freqx, self.binsx = np.histogram(self.xdata)
            self.binscenters_x = np.array([0.5 * (self.binsx[i] + self.binsx[i + 1]) for i in range(len(self.binsx) - 1)])
            self.freqx = self.freqx / np.max(self.freqx)
            self.x_bar.setOpts(x=self.binscenters_x, height=self.freqx, width=self.binsx[2] - self.binsx[3])
            self.fitLine_x.setData([0], [0])

            # update yhist
            self.freqy, self.binsy = np.histogram(self.ydata)
            self.binscenters_y = np.array([0.5 * (self.binsy[i] + self.binsy[i + 1]) for i in range(len(self.binsy) - 1)])
            self.freqy = self.freqy / np.max(self.freqy)
            self.y_bar.setOpts(x=self.binscenters_y, height=self.freqy, width=self.binsy[2] - self.binsy[3])
            self.fitLine_y.setData([0], [0])

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.fitButton.setText(_translate("MainWindow", "Fit Gaussian"))
        self.start_stop.setText(_translate("MainWindow", "Start/Stop"))
        self.clear.setText(_translate("MainWindow", "Clear data"))


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Tags: selfdatadefnprangestartpgxdata