user3794592
user3794592

Reputation: 183

Create multiple surface plots in GUI

so I just started a new project in which I need to present data I collected on a GUI. For that purpose I created a test script, that reads the data from a .mat file and then calculates the surface plots. So far everything is working. Now I need to start with the GUI. I already managed to create an other test program that can open the OpenFileName-Dialog and reads the data from the file.

from PyQt5 import QtCore, QtGui, QtWidgets
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as Navi
from matplotlib.figure import Figure
import seaborn as sns
import pandas as pd
import sip
import h5py
import mat73
import numpy as np

class MatplotlibCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width = 5, height = 4, dpi = 120):
        fig = Figure(figsize = (width,height))
        self.axes = fig.add_subplot(111)
        super(MatplotlibCanvas,self).__init__(fig)
        fig.tight_layout()

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1466, 910)
        font = QtGui.QFont()
        font.setFamily("Tahoma")
        MainWindow.setFont(font)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(280, 0, 561, 441))
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView_2 = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView_2.setGeometry(QtCore.QRect(860, 0, 561, 441))
        self.graphicsView_2.setObjectName("graphicsView_2")
        self.graphicsView_3 = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView_3.setGeometry(QtCore.QRect(280, 440, 561, 441))
        self.graphicsView_3.setObjectName("graphicsView_3")
        self.graphicsView_4 = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView_4.setGeometry(QtCore.QRect(860, 440, 561, 441))
        self.graphicsView_4.setObjectName("graphicsView_4")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(40, 90, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.action_Open = QtWidgets.QAction(MainWindow)
        self.action_Open.setObjectName("action_Open")
        self.action_Save = QtWidgets.QAction(MainWindow)
        self.action_Save.setObjectName("action_Save")
        self.action_Export = QtWidgets.QAction(MainWindow)
        self.action_Export.setObjectName("action_Export")
        self.action_Exit = QtWidgets.QAction(MainWindow)
        self.action_Exit.setObjectName("action_Exit")

        self.filename = ''
        self.canv = MatplotlibCanvas(self)
        self.df = []

        self.toolbar = Navi(self.canv, self.centralwidget)

        self.pushButton.clicked.connect(self.getFile)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def getFile(self):
        """ this function will get the adress of the mat file location
            also calls a readData function
        """
        self.filename = QFileDialog.getOpenFileName(filter="mat (*.mat)")[0]
        print("File: ", self.filename)
        self.readData()

    def readData(self):
        self.df = mat73.loadmat(self.filename, use_attrdict=True)
        struct = self.df['DemoData']
        print(struct.Nr.data)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Open "))
        self.action_Open.setText(_translate("MainWindow", "&Open"))
        self.action_Save.setText(_translate("MainWindow", "&Save"))
        self.action_Export.setText(_translate("MainWindow", "&Export"))
        self.action_Exit.setText(_translate("MainWindow", "&Quit"))


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_())

Since I can read the data, next step would be to create the surface plots and display the data. My idea was to use the graphicsView elements to display the four needed plots, but I just can't find how to link the figures, I used in the first test program (without GUI) to the graphicsView element. For the figure I used the following code line:

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
surf = ax.plot_surface(pArray, rArray, trArray, alpha = 0.5)
surf = ax.plot_surface(pArray, rArray, tArray, cmap=cm.jet, alpha = 1)

Can someone give me a tip, how I could achieve that?

Edit: I uploaded a .mat File .mat File

Upvotes: 0

Views: 97

Answers (1)

eyllanesc
eyllanesc

Reputation: 243993

I have to note that:

  • mat73 has trouble reading the provided .mat so I use scipy.
  • The data contained in the .mat are one-dimensional arrays so they could not form a surface since for this two-dimensional arrays are required so I will only show how to draw the points.
  • Due to the large number of dots, painting takes time and may freeze

The logic is to work with the FigureCanvas and create 3d plots:

from functools import cached_property

from PyQt5.QtWidgets import QApplication, QFileDialog, QMainWindow

from matplotlib.backends.backend_qt5agg import (
    FigureCanvas,
    NavigationToolbar2QT as NavigationToolbar,
)
from matplotlib.figure import Figure
from matplotlib import cm

import scipy.io as sio


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.ax = self.canvas.figure.add_subplot(projection="3d")
        self.setCentralWidget(self.canvas)
        self.addToolBar(self.toolbar)

        file_menu = self.menuBar().addMenu("&File")
        open_action = file_menu.addAction("&Open")

        open_action.triggered.connect(self.handle_open_action_triggered)

    @cached_property
    def canvas(self):
        return FigureCanvas()

    @cached_property
    def toolbar(self):
        return NavigationToolbar(self.canvas, self)

    def handle_open_action_triggered(self):
        filename, _ = QFileDialog.getOpenFileName(self, filter="mat (*.mat)")
        if filename:
            self.load_mat(filename)

    def load_mat(self, filename):
        
        res = sio.loadmat(filename)
        record = res["record"]
        data = record["Data"]
        temp_ref = data[0, 0]["TempRef"][0, 0][0, 0]["data"]
        nr = data[0][0]["Nr"][0, 0][0, 0]["data"]
        temp_act = data[0, 0]["TempAct"][0, 0][0, 0]["data"]
        self.update_plot(temp_ref, nr, temp_act)


    def update_plot(self, x, y, z):
        print(x.shape, y.shape, z.shape)
        self.ax.scatter(x, y, z)
        self.canvas.draw()




if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 3

Related Questions