1

I had a question yesterday about how to update an embedded matplotlib plot in a pyqt5 gui with toolbar which works fine now. But in my application it is more complex compared to the minimal example.

I have a class that is doing the analysis and creating plots via matplotlib while the GUI is in a separated class in another file. I made a modified minimal example:

# -*- coding: utf-8 -*-

import sys
import numpy as np

from PyQt5 import QtCore, QtWidgets, uic

import matplotlib
matplotlib.use('QT5Agg')

import matplotlib.pylab as plt

from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvas, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure

class Analysis():

    def __init__(self):

        self.fig, self.ax1 = plt.subplots()

        bins = np.arange(0.1, 2, 0.02)
        data = np.random.rand(3,2)        
        self.ax1.hist(data, bins, alpha=0.6, density=False, cumulative=False)      

    def getAxis(self):
        return self.ax1


class MyWindow(QtWidgets.QMainWindow):

    def __init__(self):

        super(MyWindow, self).__init__()
        uic.loadUi('test.ui', self) 

        # default data
        data = np.array([0.7,0.7,0.7,0.8,0.9,0.9,1.5,1.5,1.5,1.5])        
        self.fig, self.ax1 = plt.subplots()

        bins = np.arange(0.1, 2, 0.02)
        n1, bins1, patches1 = self.ax1.hist(data, bins, alpha=0.6, density=False, cumulative=False)

        # plot
        self.plotWidget = FigureCanvas(self.fig)
        self.lay = QtWidgets.QVBoxLayout(self.content_plot)  
        self.lay.setContentsMargins(0, 0, 0, 0)      
        self.lay.addWidget(self.plotWidget)

        # add toolbar
        self.addToolBar(QtCore.Qt.BottomToolBarArea, NavigationToolbar(self.plotWidget, self))        

        # button event
        self.pushButton.clicked.connect(self.update)

        # show window
        self.show() 

    #############################################     

    def update(self):

        # clear local axis
        self.ax1.cla()   

        # get axis from analysis object
        a = Analysis()        
        ax = a.getAxis()

        # ???????????
        self.ax1 = ax

        # draw the new content
        self.fig.canvas.draw_idle()  



if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    sys.exit(app.exec_())

The idea is to create a matplotlib object in the Analysis class and to store the axes of the results to get them in another method to plot it on an embedded PyQt5 widget.

But my code doesn't work. It cleans the local axes but it doesn't set the axes from the Analysis object. How can I do that correctly?

Thanks!

1 Answer 1

3

You are creating a new figure and axes in your class Analysis. You cannot take one axes from one figure and put it in another figure just like that. Instead, design your Analysis class so it takes an Axes object at initialization.

You may want to read matplotlib's coding style document.

class Analysis():
    def __init__(self, ax=None):
        if ax is None:
            ax = plt.gca()

        bins = np.arange(0.1, 2, 0.02)
        data = np.random.rand(3,2)        
        ax.hist(data, bins, alpha=0.6, density=False, cumulative=False)

(...)

    def update(self):

        # clear local axis
        self.ax1.cla()   
        a = Analysis(ax=self.ax1)        
        self.fig.canvas.draw_idle()
Sign up to request clarification or add additional context in comments.

3 Comments

Well, I want to have the analysis and the GUI separated because the analysis is used by different other programs. This is why I'm looking for a way to create a plot outside the GUI program and transfer it.
Then you should use numpy hist to get the count of values in each bin, return that from your analysis function and use a separate function in your plotting class to do the actual plotting
I changed the general design of the code. In the "core" I do all the analysis but plotting is now shifted to the GUI part. I agree that this is the easiest way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.