2021年2月9日星期二

issues in displaying matplotlib animated plot in pyqt5 gui and save in mp4 at the same time

Goal: display and save plot in mp4 at the same time

I am able to save the video but when it finishes saving, it starts to override canvases which leads to crashes and doesnt show the plot in gui. I imagine i have to use some sort of threads to run animation but i am stuck how to do that. I can also imagine a lot flaws in my code.

excel file could be any data like:

Real 1  Imaginary 1     Real 2  Imaginary 2 Real 3  Imaginary 3 Real 4  Imaginary 4 Real 5  Imaginary 5  39.0586 -10.06994   35.87842    -5.79761    34.99985    -6.42238    34.48957    -6.90717    34.19481    -7.60489  39.1207 -12.77676   35.94773    -13.95024   35.04656    -18.68319   34.51118    -24.04595   34.1874 -29.65512    

main.py

import matplotlib.animation as animation  from matplotlib import style  import csv  import os.path  from os import path    import matplotlib.animation as animation    from PyQt5 import QtCore, QtGui, QtWidgets  from PyQt5.QtWidgets import QMessageBox  from PyQt5.QtWidgets import *  from PyQt5.QtCore import *  import datetime  import serial.tools.list_ports  from pyqtgraph import PlotWidget, plot  import pyqtgraph as pg  import random  from numpy import diff  import numpy as np  LARGE_FONT = ("Verdana", 12)  import pandas as pd  style.use('fivethirtyeight')      import numpy as np  from matplotlib import pyplot as plt  from matplotlib import animation  from PyQt5 import QtCore, QtGui, QtWidgets  from PyQt5.QtWidgets import (QTreeWidget, QTreeWidgetItem, QPushButton, QLabel, QDialog, QVBoxLayout, QApplication, QLineEdit)  from PyQt5.QtWidgets import (QPushButton, QDialog, QTreeWidget,                               QTreeWidgetItem, QVBoxLayout,                               QHBoxLayout, QFrame, QLabel, QComboBox,                               QApplication, QTreeWidgetItemIterator, QMessageBox, QProxyStyle)  from PyQt5.QtCore import *  from PyQt5.QtGui import *  from PyQt5.QtWidgets import *  import sys    import matplotlib  from matplotlib.figure import Figure  matplotlib.use('QT5Agg')  from matplotlib.backends.backend_qt5agg import  FigureCanvas  from matplotlib.backends.backend_qt5agg import  NavigationToolbar2QT as NavigationToolbar    plt.rcParams['animation.ffmpeg_path'] =  'C:/ffmpeg/bin/ffmpeg.exe'  from anim import Ui_MainWindow  plt.ion()    writer = animation.FFMpegWriter()      plt.show()  class Test(QtWidgets.QMainWindow):      def __init__(self, parent = None):          super().__init__(parent)          QtWidgets.QMainWindow.__init__(self, parent)          self.i = 0          self.ui = Ui_MainWindow()          self.ui.setupUi(parent)                    vlay1 = QVBoxLayout()          self.plotWidget1 = FigureCanvas(Figure())          toolbar1 = NavigationToolbar(self.plotWidget1, self)                    openButton = QtWidgets.QPushButton("Open a file")          sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)          sizePolicy.setHorizontalStretch(0)          sizePolicy.setVerticalStretch(0)          sizePolicy.setHeightForWidth(openButton.sizePolicy().hasHeightForWidth())          openButton.setSizePolicy(sizePolicy)          dateTimeEdit = QtWidgets.QDateTimeEdit()          sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)          sizePolicy.setHorizontalStretch(0)          sizePolicy.setVerticalStretch(0)          sizePolicy.setHeightForWidth(dateTimeEdit.sizePolicy().hasHeightForWidth())          dateTimeEdit.setSizePolicy(sizePolicy)                    vlay1.addWidget(openButton)          vlay1.addWidget(dateTimeEdit)          vlay1.addWidget(toolbar1)          vlay1.addWidget(self.plotWidget1)          self.ui.gridLayout.addLayout(vlay1, 0, 0, 1, 1)          openButton.clicked.connect(self.openFile)            self.ax1 = self.plotWidget1.figure.subplots()          self.line, = self.ax1.plot([], [], marker='o')          self.ax1.set_xlabel("Real")          self.ax1.set_ylabel("Imaginary")                    self.ax1.relim()          self.ax1.autoscale_view(True, True, True)          self.ax1.set_title(str(self.i))          self.plotWidget1.figure.tight_layout()          self.openFile()          anim = animation.FuncAnimation(self.plotWidget1.figure, self.animate, init_func=self.init,                                 frames=self.len-1, interval=1, blit=True)          anim.save('plot.mp4', writer=writer, dpi=300, )                  def readFile(self):          df = pd.read_excel(self.fileName)          self.Real1 = df["Real 1"]          self.Real2 = df["Real 2"]          self.Real3 = df["Real 3"]          self.Real4 = df["Real 4"]          self.Real5 = df["Real 5"]          self.Img1 = df["Imaginary 1 "]          self.Img2 = df["Imaginary 2"]          self.Img3 = df["Imaginary 3"]          self.Img4 = df["Imaginary 4"]          self.Img5 = df["Imaginary 5"]                    self.len = len(self.Img1)                  def getDataX(self):          self.i += 1          if self.i == self.len - 1:              print("complete")          return [self.Real1[self.i], self.Real2[self.i], self.Real3[self.i], self.Real4[self.i], self.Real5[self.i]]        def getDataY(self):                   return [abs(self.Img1[self.i]), abs(self.Img2[self.i]), abs(self.Img3[self.i]), abs(self.Img4[self.i]), abs(self.Img5[self.i])]                      def openFile(self):          dirAndName = QtWidgets.QFileDialog.getOpenFileName(self,'Open a File', "*.xlsx")          if dirAndName[0] != []:              self.fileName = dirAndName[0]              self.readFile()          print(dirAndName)                def init(self):          self.line.set_data([], [])          return self.line,        def animate(self, i):          x = self.getDataX()          y = self.getDataY()                    x = np.asarray(x)          y = np.asarray(y)                    self.ax1.set_title(str(self.i))          self.line.set_data(x, y)          self.ax1.relim()          self.ax1.autoscale_view(True, True, True)          return self.line,    def Home():      f = QtWidgets.QMainWindow()            #f.resize(1699, 980)      c = Test(f)            f.show()            r = qApp.exec_()    if __name__ == "__main__":      qApp = QtWidgets.QApplication(sys.argv)      qApp.setStyle(QStyleFactory.create('Fusion'))      proxy = QProxyStyle(qApp.style())      qApp.setStyle(proxy)      Home()    

Anim.py

from PyQt5 import QtCore, QtGui, QtWidgets      class Ui_MainWindow(object):      def setupUi(self, MainWindow):          MainWindow.setObjectName("MainWindow")          MainWindow.resize(800, 600)          self.centralwidget = QtWidgets.QWidget(MainWindow)          self.centralwidget.setObjectName("centralwidget")          self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)          self.gridLayout.setObjectName("gridLayout")          self.verticalLayout = QtWidgets.QVBoxLayout()          self.verticalLayout.setObjectName("verticalLayout")          self.pushButton = QtWidgets.QPushButton(self.centralwidget)          sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)          sizePolicy.setHorizontalStretch(0)          sizePolicy.setVerticalStretch(0)          sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())          self.pushButton.setSizePolicy(sizePolicy)          self.pushButton.setObjectName("pushButton")          self.verticalLayout.addWidget(self.pushButton)          self.dateTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)          sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)          sizePolicy.setHorizontalStretch(0)          sizePolicy.setVerticalStretch(0)          sizePolicy.setHeightForWidth(self.dateTimeEdit.sizePolicy().hasHeightForWidth())          self.dateTimeEdit.setSizePolicy(sizePolicy)          self.dateTimeEdit.setObjectName("dateTimeEdit")          self.verticalLayout.addWidget(self.dateTimeEdit)          self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)          MainWindow.setCentralWidget(self.centralwidget)          self.menubar = QtWidgets.QMenuBar(MainWindow)          self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))          self.menubar.setObjectName("menubar")          MainWindow.setMenuBar(self.menubar)          self.statusbar = QtWidgets.QStatusBar(MainWindow)          self.statusbar.setObjectName("statusbar")          MainWindow.setStatusBar(self.statusbar)            self.retranslateUi(MainWindow)          QtCore.QMetaObject.connectSlotsByName(MainWindow)        def retranslateUi(self, MainWindow):          _translate = QtCore.QCoreApplication.translate          MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))          self.pushButton.setText(_translate("MainWindow", "Open File"))      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_())    

*** I am using Anim.py for other reasons, even though my main.py is creating qpushbutton and qtimeedit again***

https://stackoverflow.com/questions/66125944/issues-in-displaying-matplotlib-animated-plot-in-pyqt5-gui-and-save-in-mp4-at-th February 10, 2021 at 03:39AM

没有评论:

发表评论