How Does a Pyqtgraph Export for Three Subplots Look Like?

420 views
Skip to first unread message

GR

unread,
Sep 10, 2018, 12:23:07 PM9/10/18
to pyqtgraph
Hi,

I posted a question on stackoverflow:


I am unsure about how much attention it would rise there. Therefore I would like to draw your attention to that question.

I hope you do not mind.

If you have an idea how my question can be solved: thanks in advance!

Gerhard

Patrick

unread,
Sep 10, 2018, 10:29:39 PM9/10/18
to pyqtgraph
Hi,
I'm pretty sure you can do this (update plot and export, without plot being updated on screen), but I think the plot axes still needs to be displayed somewhere initially so that the mapping from plot to device coordinates gets set up. Maybe there's a way to do that without showing the plot window, but I don't know.

In your example code you never call app.exec_(), so the Qt event loop never starts, so none of the required initialisation happens. If you run a normal app with the window displayed, then trigger the export from a button/timer/event etc, then it should work.

As an aside, I use pyqtgraph to plot inside my applications due to fast screen updates and interactivity, but produce output plot files with matplotlib (as pdf or png). So when the user hits the "save" button, I pass the data off to a separate matplotlib plotting method as it has prettier and more flexible plotting options. For performance, you can keep the matplotlib figure around and just modify the plot data with set_data methods rather than recreating the whole plot again. If that still isn't fast enough, then maybe store raw data and analyse/plot afterwards. 

GR

unread,
Sep 11, 2018, 12:33:24 PM9/11/18
to pyqtgraph
Hi Patrick,

thanks, that was already helpful. 

You are right that the call to app.exec_() was missing for a proper display. And with that, indeed, I can execute the export from the gui.

My boilerplate for exporting was http://www.pyqtgraph.org/documentation/exporting.html and so I thought I could work without the app.exec_().

So perhaps you know what I have to pass as a proper plotItem instance?

Thanks in advance!

Patrick

unread,
Sep 11, 2018, 9:06:42 PM9/11/18
to pyqtgraph
The "entire scene" export item is the GraphicsLayout object that then contains the multiple PlotItem objects. Demo code below (Note on Linux you can overwrite an open file, so can see exported image being updated in realtime, probably can't do that on Windows).

import numpy as np
from PyQt5 import QtWidgets
import pyqtgraph as pg
import pyqtgraph.exporters
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph import GraphicsLayoutWidget

class PyQtGraphExportTest(GraphicsLayoutWidget):

    def __init__(self):
    
        super().__init__()

        self.setWindowTitle('Test pyqtgraph export')
        self.resize(640, 400)

        # Set up a couple of stacked plots
        self.plot1 = self.addPlot(row=0, col=0)
        self.trace1 = self.plot1.plot(np.random.random(10))
        self.plot1.enableAutoRange(pg.ViewBox.XYAxes)
        self.plot2 = self.addPlot(row=1, col=0)
        self.trace2 = self.plot2.plot(np.random.random(10))
        self.plot2.enableAutoRange(pg.ViewBox.XYAxes)

        # Store reference to exporter so it doesn't have to be initialised every
        # time it's called. Note though the window needs to be displayed so
        # mapping from plot to device coordinates is set up, that hasn't
        # happened yet as this GraphicsLayoutWidget is also the Qt app window,
        # so we'll create it later on.
        self.exporter = None

        # Configure a timer to act as trigger event for export. This could be a
        # data acquisition event, button press etc.
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update_data)
        self.timer.start(2000)

    def update_data(self):
        # Create the exporter if needed, now window is displayed on screen
        if not self.exporter:
            # Here we are passing the exporter the GraphicsLayout object that is
            # the central item (ci) inside this GraphicsLayoutWidget. That in
            # turn contains the two PlotItem objects. 
            self.exporter = pg.exporters.ImageExporter(self.ci)
            self.exporter.parameters()['width'] = 640
        # Get some new data, update plot and export
        self.trace1.setData(np.random.random(10))
        self.trace2.setData(np.random.random(10))
        self.exporter.export('exported_image.png')

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = PyQtGraphExportTest()
    window.show()
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        sys.exit(app.exec_())



GR

unread,
Sep 11, 2018, 9:51:21 PM9/11/18
to pyqtgraph
Hi Patrick,

you made my day!

This is the framework I already can work with from scratch. Perfect!

0.04 seconds on average per export. Super!

I will post your code as an (unaccepted) answer in stackoverflow, as still others might see it there and could benefit from it.

Thanks again!
Reply all
Reply to author
Forward
0 new messages