The graph is not drawn in the matplotlib - python

I'm drawing a graph in the matplotlib by converting to FFT with Arduino data. However, the same error does not cause a graph. I think it's because of self in update() what should I do? I don't know how to change when there is a Typeerror in my code. If you find a problem, can you tell me?
+ I solved the error. However, the graph is not printed. The code has been modified as a whole. What happen?
from PyQt5.QtWidgets import*
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import random
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
import serial
import time
import random
import numpy as np
from matplotlib import animation
from collections import deque # import a "circular" list
from threading import Thread, Lock
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1212, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.widget = matplotlibWidget()
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 0, 1, 1)
self.centralwidget.setLayout(self.gridLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
#from matplotlibwidgetFile import matplotlibWidget
class matplotlibWidget(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self,parent)
self.i = 0
self.data = []
lock = Lock()
freq = 2000 # 1/T
self.guarda = 100 # 200
r = range(0, int(freq/2+1), int(freq/self.guarda))
self.frequencia = np.fft.fftfreq(self.guarda, d=1/freq)
self.acelx = deque([], maxlen=self.guarda)
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.right_layout = QVBoxLayout()
self.right_layout.addWidget(self.canvas)
self.setLayout(self.right_layout)
self.ax.set_xlim((0,int(freq/2)))
self.ax.set_ylim((0,1000))
self.line, = self.ax.plot([],[])
self.ax.grid(True)
def data_input():
for line in arduinoData:
try:
self.i+=1
self.acelx.append(float(line))
with lock:
if self.i > len(self.acelx):
self.data = np.fft.fft(self.acelx)
except ValueError:
pass
t = Thread(target=data_input)
t.daemon = True
t.start()
S = Scope(self.line,self.frequencia, self.guarda, self.data, self.ax, self.acelx, self.i )
timer = QtCore.QTimer()
timer.timeout.connect(S.update)
timer.start(0)
class Scope(matplotlibWidget) :
def __init__(self, line, frequencia, guarda, data, ax, acelx, i) :
self.line, = line,
self.ax = ax
self.frequencia = frequencia
self.guarda = guarda
self.data = data
self.acelx = acelx
self.i = i
def update(self) :
if self.i > len(self.acelx) :
self.line.set_data(self.frequencia[:int(self.guarda/2)], abs(np.real(self.data[:int(self.guarda/2)])))
self.ax.figure.canvas.draw()
return (self.line,)
if __name__ == "__main__":
import sys
value = [0,0,0,0,0,0,0,0,0,0]
arduinoData = serial.Serial('com5', 9600)
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

You have to create instance:
s = Scope()
timer = QtCore.QTimer()
timer.timeout.connect(s.update)
or
timer = QtCore.QTimer()
timer.timeout.connect(Scope().update)

Related

PyQt5 3D scatterplot widget not showing up

Goal: Generate a 3D scatter plot from radar data obtained from vTrig_DataCollect.
Scatterplot_widget is not being shown in the MainWindow.
Step 1 is to make the plot show up from a single data collection.
Step 2 is to repeatedly call vTrig_DataCollect and have the plot refresh at 1 Hz.
from PyQt5 import QtCore, QtGui, QtWidgets
import time
from PyQt5 import QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import vTrig_DataCollect
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
MainWindow.setCentralWidget(self.centralwidget)
self.scatterplot_widget = QtWidgets.QWidget(self.centralwidget)
self.scatterplot_widget.setGeometry(QtCore.QRect(0, 0, 800, 500))
self.scatterplot_widget.setObjectName("scatterplot_widget")
self.fig = Figure()
self.canvas = FigureCanvas(self.fig)
self.axes = self.fig.add_subplot(111, projection='3d')
payload_data = vTrig_DataCollect.data_collect()
x_points = payload_data['x']
y_points = payload_data['y']
z_points = payload_data['z']
intensity = payload_data['intensity']
self.scatterplot_widget = self.axes.scatter(x_points, y_points, z_points, s=4, c=intensity)
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", "Visualization_Window"))
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_())
The majority of the code was generated using Qt Designer, then I added the 9 lines of code related to my plot.
You must not modify the file generated by pyuic5 so you must restore the file by running: python -m pyuic5 your_ui.ui -o mainwindow.py -x, also I will assume that the file vTrig_DataCollect.py is:
import numpy as np
def data_collect():
N = 50
return {
"x": np.random.rand(N),
"y": np.random.rand(N),
"z": np.random.rand(N),
"intensity": np.random.rand(N),
}
The idea is to create the canvas (which is a QWidget too) and place it on top of another widget using a layout, then update the canvas with the new data.
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from mainwindow import Ui_MainWindow
import vTrig_DataCollect
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.canvas = FigureCanvas(Figure())
self.axes = self.canvas.figure.add_subplot(111, projection="3d")
lay = QVBoxLayout(self.ui.scatterplot_widget)
lay.addWidget(self.canvas)
timer = QTimer(self, interval=1000, timeout=self.handle_timeout)
timer.start()
def handle_timeout(self):
payload_data = vTrig_DataCollect.data_collect()
x_points = payload_data["x"]
y_points = payload_data["y"]
z_points = payload_data["z"]
intensity = payload_data["intensity"]
self.axes.clear()
self.axes.scatter(x_points, y_points, z_points, s=4, c=intensity)
self.canvas.draw()
def main():
app = QApplication([])
w = MainWindow()
w.show()
app.exec_()
if __name__ == "__main__":
main()

Multiple live plot GUI using pyqtgraph and PyQt5

I am trying to create a gui with several live plot EEG/ECG graphs (each plot on different axes).
From what I understand, I need to create multiple PlotWidgets inside a grid layout.
I have created a live plot using pyqtgraph, below however I am unsure how to merge this into the GUI:
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import collections
import random
import time
import math
import numpy as np
class DynamicPlotter:
def __init__(self, sampleinterval=0.1, timewindow=10., size=(600, 350)):
# Data stuff
self.interval = int(sampleinterval * 1000)
self.bufsize = int(timewindow / sampleinterval)
self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
self.x = np.linspace(-timewindow, 0.0, self.bufsize)
self.y = np.zeros(self.bufsize, dtype=float)
# PyQtGraph stuff
self.app = QtGui.QApplication([])
self.plt = pg.plot(title='EEG/ECG Live Plot')
self.plt.resize(*size)
self.plt.showGrid(x=True, y=True)
#self.plt.setXRange(5,20, padding=0)
self.plt.setLabel('left', 'Amplitude', 'uVrms')
self.plt.setLabel('bottom', 'Time', 's')
self.curve = self.plt.plot(self.x, self.y, pen=(255, 0, 0))
# QTimer
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updateplot)
self.timer.start(self.interval)
def getdata(self):
frequency = 0.5
noise = random.normalvariate(0., 1.)
new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
return new
def updateplot(self):
self.databuffer.append(self.getdata())
self.y[:] = self.databuffer
self.curve.setData(self.x, self.y)
self.app.processEvents()
def run(self):
self.app.exec_()
if __name__ == '__main__':
livePlot = DynamicPlotter(sampleinterval=0.05, timewindow=5.)
livePlot.run()
Here is the basic GUI (3 plot widgets inside grid, and a few labels in mainWindow):
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(845, 727)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.labelTitle = QtWidgets.QLabel(self.centralwidget)
self.labelTitle.setGeometry(QtCore.QRect(280, 0, 291, 51))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.labelTitle.setFont(font)
self.labelTitle.setObjectName("labelTitle")
self.labelCh1 = QtWidgets.QLabel(self.centralwidget)
self.labelCh1.setGeometry(QtCore.QRect(20, 90, 31, 51))
self.labelCh1.setObjectName("labelCh1")
self.labelCh2 = QtWidgets.QLabel(self.centralwidget)
self.labelCh2.setGeometry(QtCore.QRect(20, 180, 31, 51))
self.labelCh2.setObjectName("labelCh2")
self.labelCh3 = QtWidgets.QLabel(self.centralwidget)
self.labelCh3.setGeometry(QtCore.QRect(20, 260, 31, 51))
self.labelCh3.setObjectName("labelCh3")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(70, 70, 741, 261))
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.ch1PlotWidget = PlotWidget(self.widget)
self.ch1PlotWidget.setObjectName("ch1PlotWidget")
self.gridLayout.addWidget(self.ch1PlotWidget, 0, 0, 1, 1)
self.ch2PlotWidget = PlotWidget(self.widget)
self.ch2PlotWidget.setObjectName("ch2PlotWidget")
self.gridLayout.addWidget(self.ch2PlotWidget, 1, 0, 1, 1)
self.ch3PlotWidget = PlotWidget(self.widget)
self.ch3PlotWidget.setObjectName("ch3PlotWidget")
self.gridLayout.addWidget(self.ch3PlotWidget, 2, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 845, 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.labelTitle.setText(_translate("MainWindow", "EEG/ECG Recording GUI"))
self.labelCh1.setText(_translate("MainWindow", "Ch 1"))
self.labelCh2.setText(_translate("MainWindow", "Ch 2"))
self.labelCh3.setText(_translate("MainWindow", "Ch 3"))
from pyqtgraph import PlotWidget
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_())
My question is how do I integrate these two so I can plot the live graphs in each widget?
Ideally I want to use a super class so I can simply import the unedited gui.
I have tried importing the gui.Ui_MainWindow into the class and then overwriting the self.plt to self.Ch1PlotWidget
from pyqtgraph.Qt import QtGui, QtCore, QtWidgets
import gui as gui
import sys
import pyqtgraph as pg
import collections
import random
import time
import math
import numpy as np
class MainWindow(QtWidgets.QMainWindow, gui.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.setupUi(self)
# Data stuff
self.interval = 100
self.bufsize = int(10 / self.interval)
self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
self.x = np.linspace(-10, 0.0, self.bufsize)
self.y = np.zeros(self.bufsize, dtype=float)
# PyQtGraph stuff
self.app = QtGui.QApplication([])
self.ch1PlotWidget = pg.plot(title='Live Plot')
self.ch1PlotWidget.resize(600, 350)
self.ch1PlotWidget.showGrid(x=True, y=True)
# self.plt.setXRange(5,20, padding=0)
self.ch1PlotWidget.setLabel('left', 'Amplitude', 'uVrms')
self.ch1PlotWidget.setLabel('bottom', 'Time', 's')
self.curve = self.ch1PlotWidget.plot(self.x, self.y, pen=(255, 0, 0))
# QTimer
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updateplot)
self.timer.start(self.interval)
def getdata(self):
frequency = 0.5
noise = random.normalvariate(0., 1.)
new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
return new
def updateplot(self):
self.databuffer.append(self.getdata())
self.y[:] = self.databuffer
self.curve.setData(self.x, self.y)
self.app.processEvents()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Sorry for all the code, I am just very confused on how to implement logic to the gui.
Here is an option where you can use both classes with minimal changes.
Change the DynamicPlotter constructor to accept a PlotWidget as a argument instead of creating a new one, since they are created and added to a layout in Ui_Mainwindow. In the MainWindow class, create a DynamicPlotter object for each plot (and keep a persistent reference, in this case I added them to a list self.plots).
class DynamicPlotter:
def __init__(self, plot, sampleinterval=0.1, timewindow=10., size=(600, 350)):
# Data stuff
self.interval = int(sampleinterval * 1000)
self.bufsize = int(timewindow / sampleinterval)
self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
self.x = np.linspace(-timewindow, 0.0, self.bufsize)
self.y = np.zeros(self.bufsize, dtype=float)
# PyQtGraph stuff
self.plt = plot
self.plt.setTitle('EEG/ECG Live Plot')
self.plt.resize(*size)
self.plt.showGrid(x=True, y=True)
#self.plt.setXRange(5,20, padding=0)
self.plt.setLabel('left', 'Amplitude', 'uVrms')
self.plt.setLabel('bottom', 'Time', 's')
self.curve = self.plt.plot(self.x, self.y, pen=(255, 0, 0))
# QTimer
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updateplot)
self.timer.start(self.interval)
def getdata(self):
frequency = 0.5
noise = random.normalvariate(0., 1.)
new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
return new
def updateplot(self):
self.databuffer.append(self.getdata())
self.y[:] = self.databuffer
self.curve.setData(self.x, self.y)
class MainWindow(QtWidgets.QMainWindow, gui.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.setupUi(self)
self.plots = []
for plot in (self.ch1PlotWidget, self.ch2PlotWidget, self.ch3PlotWidget):
self.plots.append(
DynamicPlotter(plot, sampleinterval=0.05, timewindow=5.)
)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

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

Real time audio plot

I am trying to plot microphone speech (real time) with python and matplotlib.
Here is what i have done:
file:chart_1.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import dates as mpl_dates
from matplotlib.animation import FuncAnimation
from pydub import AudioSegment
import numpy as np
import datetime
import pyaudio
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# constants
self.CHUNK = int(16384/4)
self.CHUNK_TIME = 125 #msec
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 32750
self.p = pyaudio.PyAudio()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(630, 200)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(0, 200))
MainWindow.setMaximumSize(QtCore.QSize(16777215, 200))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
MainWindow.setCentralWidget(self.centralwidget)
self.chart = Canvas(self)
self.chart.ax.set_facecolor((1,1,1))
self.chart.ax.tick_params(labelcolor='white')
self.stream = self.p.open(format=self.FORMAT,channels=self.CHANNELS,rate=self.RATE,input=True,output=True,frames_per_buffer=self.CHUNK)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Microphone chart"))
def plot_microphone_data(self):
now = datetime.datetime.now()
self.x_vals = []
self.y_vals = []
while(True):
data = self.stream.read(self.CHUNK)
#slice = AudioSegment(data, sample_width=2, frame_rate=self.RATE, channels=1)
#print(len(slice))
#print(len(slice.raw_data))
self.stream.write(data)
audio_data = np.frombuffer(data, np.int16)
self.chart.li.set_xdata(np.arange(len(audio_data)))
self.chart.li.set_ydata(audio_data)
self.chart.fig.canvas.draw()
self.chart.fig.canvas.flush_events()
class Canvas(FigureCanvas):
def __init__(self,parent):
self.fig , self.ax = plt.subplots(figsize=(5,4),dpi=200)
self.fig.patch.set_facecolor((6/255,21/255,154/255))
self.ax.set_position([0., 0, 1., 0.8])
self.ax.xaxis.tick_top()
self.ax.tick_params(color=(1,1,1))
super().__init__(self.fig)
parent.verticalLayout.addWidget(self)
plt.cla()
plt.xticks(fontsize=5)
self.ax.grid(False)
self.li, = self.ax.plot([], [])
self.ax.set_xlim(0,1000)
self.ax.set_ylim(-8000,8000)
self.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
ui.plot_microphone_data()
sys.exit(app.exec_())
works well, but it hasn't time in x axis so i have made the file chart_2.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import dates as mpl_dates
from matplotlib.animation import FuncAnimation
from pydub import AudioSegment
import numpy as np
import datetime
import pyaudio
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# constants
self.CHUNK = int(16384/4)
self.CHUNK_TIME = 125 #msec
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 32750
self.TIME_WINDOW = 3000 #display 3 seconds on chart
self.p = pyaudio.PyAudio()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(630, 200)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(0, 200))
MainWindow.setMaximumSize(QtCore.QSize(16777215, 200))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
MainWindow.setCentralWidget(self.centralwidget)
self.chart = Canvas(self)
self.chart.ax.set_facecolor((1,1,1))
self.chart.ax.tick_params(labelcolor='white')
self.stream = self.p.open(format=self.FORMAT,channels=self.CHANNELS,rate=self.RATE,input=True,output=True,frames_per_buffer=self.CHUNK,stream_callback=self.microphone_callback)
self.x_vals = np.array([])
self.y_vals = np.array([])
self.now = datetime.datetime.now()
self.stream.start_stream()
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Microphone chart"))
def microphone_callback(self,in_data, frame_count, time_info, status):
data = in_data
#slice = AudioSegment(data, sample_width=2, frame_rate=self.RATE, channels=1)
#print(len(slice))
#print(len(slice.raw_data))
audio_data = np.frombuffer(data, np.int16)
time_data = np.array([])
for i in range(0,len(audio_data)):
time_data = np.append(time_data, self.now)
self.now = self.now+datetime.timedelta(milliseconds=self.CHUNK_TIME/len(audio_data))
self.x_vals = np.concatenate((self.x_vals, time_data), axis=0)
self.y_vals = np.concatenate((self.y_vals, audio_data), axis=0)
if(self.x_vals.size>audio_data.size*(self.TIME_WINDOW/self.CHUNK_TIME)):
self.x_vals = self.x_vals[audio_data.size:]
self.y_vals = self.y_vals[audio_data.size:]
self.chart.li.set_xdata(self.x_vals)
self.chart.li.set_ydata(self.y_vals)
x_ticks = []
for i in range(0,self.TIME_WINDOW+1,1000):
tick = self.x_vals[0]+datetime.timedelta(milliseconds=i)
x_ticks.append(tick)
plt.xticks(x_ticks)
self.chart.ax.set_xlim(x_ticks[0],x_ticks[-1])
self.chart.fig.canvas.draw()
self.chart.fig.canvas.flush_events()
return (data, pyaudio.paContinue)
class Canvas(FigureCanvas):
def __init__(self,parent):
self.fig , self.ax = plt.subplots(figsize=(5,4),dpi=200)
self.fig.patch.set_facecolor((6/255,21/255,154/255))
self.ax.set_position([0., 0, 1., 0.8])
self.ax.xaxis.tick_top()
self.ax.tick_params(color=(1,1,1))
super().__init__(self.fig)
parent.verticalLayout.addWidget(self)
self.now = datetime.datetime.now()
self.chart_stop = self.now+datetime.timedelta(milliseconds=parent.TIME_WINDOW)
plt.cla()
date_format = mpl_dates.DateFormatter("%H:%M:%S")
plt.gca().xaxis.set_major_formatter(date_format)
plt.xticks(fontsize=5)
self.ax.grid(False)
self.li, = self.ax.plot([], [])
self.ax.set_ylim(-8000,8000)
x_ticks = []
for i in range(0,parent.TIME_WINDOW+1,1000):
tick = self.now+datetime.timedelta(milliseconds=i)
x_ticks.append(tick)
plt.xticks(x_ticks)
self.ax.set_xlim(x_ticks[0],x_ticks[-1])
self.show()
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_())
Chart 2 has time on upper x axis but it has some delay problems.
Can you please advice me to fix that?

How to set yaxis tick label in a fixed position so that when i scroll left or right the yaxis tick label should be visible?

in my program i have taken figure first then i import figue into canvas. Then i import canvas into scroll area. when i run my program ,then if i turn left scroll the yaxis tick label goes hide or i turn right scroll the yaxis tick label goes also hide.
i have taken two axis. axis,axis2. i have set axes2.yaxis.tick_right() and axes.yaxis.tick_right().
I want that the yaxis tick label will stay at right side and alyas visible, whatever i turn scroll left or right .
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from PyQt5.QtWidgets import QMainWindow,QVBoxLayout
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
from matplotlib.dates import num2date, date2num
from mpl_finance import candlestick_ochl as candlestick
import numpy as np
import matplotlib.ticker as ticker
import matplotlib.dates as mdates
import pylab as pl
class MainWindow_code_serarch(object):
def setup_code_serarch(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(870, 680)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget1 = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget1.setGeometry(QtCore.QRect(17, 30, 741, 13))
self.verticalLayoutWidget1.setObjectName("verticalLayoutWidget")
self.verticalLayout1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget1)
self.verticalLayout1.setContentsMargins(0, 0, 0, 0)
self.verticalLayout1.setObjectName("verticalLayout1")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(17, 10, 940, 603))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.figure = Figure(figsize=(100,7.2), dpi=80, facecolor='k')
self.canvas = FigureCanvas(self.figure)
self.widget = QtWidgets.QWidget()
self.scroll_area = QtWidgets.QScrollArea(self.widget)
self.scroll_area.setWidget(self.canvas)
self.verticalLayout.addWidget(self.scroll_area)
axes,axes2 = self.figure.subplots(nrows=2, sharex=True)
data = {
'date': ['2018/10/30', '2018/11/03', '2018/11/04', '2018/11/05', '2018/11/07', '2018/11/10', '2018/11/11'],
'open': [8824, 8726.31, 8642.14, 8531.51, 8630.25, 8602.50, 8640.22],
'high': [8858, 8748.60, 8551.36, 8653.16, 8476.69, 8630, 8570.56],
'low': [8688, 8743.67, 8550.76, 8449.50, 8631.83, 8602.18, 8743.22],
'close': [8820, 8747.17, 8550.52, 8553., 8517.10, 8628.78, 8588.52],
'volume': [17759.56, 120000.17, 18739.52, 38599.50, 16517.10, 17723.78, 15588.52]
}
x = date2num([datetime.datetime.strptime(d, '%Y/%m/%d').date() for d in data['date']])
t= np.arange(len(data['date']))
candle_trace = zip(t, data['open'], data['high'], data['low'], data['close'], data['volume'])
candlestick(axes, candle_trace, width=.75, colorup='g', colordown='r')
axes2.plot(t, [1, 2, 3, 4, 7, 8, 9])
axes.set_position([0.02, 0.37, 0.88, 0.6])
axes2.set_position([0.02, 0.15, 0.88, 0.22])
axes.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
axes.yaxis.tick_right()
axes2.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
axes2.grid(color='lightgray', linewidth=.5, linestyle=':')
axes.grid(color='lightgray', linewidth=.5, linestyle=':')
axes2.yaxis.tick_right()
axes.autoscale_view()
axes2.autoscale_view()
axes.set_facecolor('#041105')
axes2.set_facecolor('#041105')
# N = len(dates)
axes.set_xticks(range(0, len((x)), 1))
axes.set_xticklabels([mdates.num2date(d).strftime('%b-%d') for d in x])
axes.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
axes2.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.canvas.draw()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 246, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
# self.pushButton.clicked.connect(self.graphShowCode)
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", "OK"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MainWindow_code_serarch()
ui.setup_code_serarch(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Output image:
when i turn scroll left output image 2:
Here is a way to scroll the content of an axes with a PyQt QtScrollBar. This is done by changing the limits of the axes depending on the scroll bar's value. To this end, a callback to the QtScrollBar's actionTriggered method is registered that changes the limits of the axes.
import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np
class ScrollableWindow(QtWidgets.QMainWindow):
def __init__(self, fig, ax, step=0.1):
plt.close("all")
if not QtWidgets.QApplication.instance():
self.app = QtWidgets.QApplication(sys.argv)
else:
self.app = QtWidgets.QApplication.instance()
QtWidgets.QMainWindow.__init__(self)
self.widget = QtWidgets.QWidget()
self.setCentralWidget(self.widget)
self.widget.setLayout(QtWidgets.QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.fig = fig
self.ax = ax
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.step = step
self.setupSlider()
self.nav = NavigationToolbar(self.canvas, self.widget)
self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.widget.layout().addWidget(self.scroll)
self.canvas.draw()
self.show()
self.app.exec_()
def setupSlider(self):
self.lims = np.array(self.ax.get_xlim())
self.scroll.setPageStep(self.step*100)
self.scroll.actionTriggered.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value()/((1+self.step)*100)
l1 = self.lims[0]+r*np.diff(self.lims)
l2 = l1 + np.diff(self.lims)*self.step
self.ax.set_xlim(l1,l2)
print(self.scroll.value(), l1,l2)
self.fig.canvas.draw_idle()
# create a figure and some subplots
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")
# pass the figure to the custom window
a = ScrollableWindow(fig,ax)
For a Scrollbar within the figure, see Scrollable Bar graph matplotlib
The above answer works well, but does not hand back control to the spyder window or python command line. Also in spyder it could be run only once. Added a few more points seen from another thread on exiting from QT window and improved to this.
import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize
class HelloWindow(QMainWindow):
def __init__(self, fig, ax , step = 0.1):
plt.close("all")
if not QtWidgets.QApplication.instance():
self.app = QtWidgets.QApplication(sys.argv)
else:
self.app = QtWidgets.QApplication.instance()
QMainWindow.__init__(self)
self.setMinimumSize(QSize(1500, 100))
self.setWindowTitle("Value Plotting")
self.step = step
self.widget = QWidget()
self.setCentralWidget( self.widget )
self.widget.setLayout(QtWidgets.QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.fig = fig
self.ax = ax
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.step = step
self.setupSlider()
self.nav = NavigationToolbar(self.canvas, self.widget)# self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.widget.layout().addWidget(self.scroll)
menu = self.menuBar().addMenu('Action for quit')
action = menu.addAction('Quit')
action.triggered.connect(QtWidgets.QApplication.quit)
self.canvas.draw()
def setupSlider(self):
self.lims = np.array(self.ax.get_xlim())
self.scroll.setPageStep(self.step*100)
self.scroll.actionTriggered.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value()/((1+self.step)*100)
l1 = self.lims[0]+r*np.diff(self.lims)
l2 = l1 + np.diff(self.lims)*self.step
self.ax.set_xlim(l1,l2)
print(self.scroll.value(), l1,l2)
self.fig.canvas.draw_idle()
if __name__ == "__main__":
def run_app(fig,ax):
app = QtWidgets.QApplication(sys.argv)
mainWin = HelloWindow(fig,ax)
mainWin.show()
app.exec_()
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")
run_app(fig,ax)
Found it running well on the python console. Exiting roughly in Spyder. Top close button not working, but exiting when operating from menu.

Categories

Resources