0

I would like a pyqtgraph counterpart to the matplotlib.pyplot.gcf() function, which returns a reference to the current figure. I would like a function that returns a reference to the current pyqtgraph GraphicsWindow instance. Is there a way to do this?

EL_DON
  • 1,416
  • 1
  • 19
  • 34

2 Answers2

1

There is no implicit "current figure" concept in pyqtgraph; each window or graphical object should be referenced explicitly. For example:

plot_window = pg.plot()

# Add data to this plot:
plot_curve = plot_window.plot(data)

# Update data in this curve:
plot_curve.setData(data)

If you just want to get the currently active window, then Qt can provide that: http://doc.qt.io/qt-5/qapplication.html#activeWindow

Luke
  • 11,374
  • 2
  • 48
  • 61
  • But there's no guarantee that the active q window is a pyqtgraph window, is there? My workaround for now is to put a wrapper around `pyqtgraph.GraphicsWindow` that adds windows to a global list on creation and intercepts close events so it can remove them from the list. It seems to work well enough so far. – EL_DON Apr 26 '18 at 02:32
  • 1
    You may be interested in this project: github.com/eldond/pgmpl . I am impressed with pyqtgraph's performance, but I have many plotting scripts using matplotlib, and I know how to make matplotlib output look nice easily. My goal is to convert my scripts to pyqtgraph by only changing the import statements, and to be able to change back just as easily. This wrapper seems to be a good way to achieve that so far. I am aware of pyqtgraph's export to mpl functionality (a great feature), but it seems incomplete and doesn't help with my legacy code. Also, https://github.com/eldond/pgmpl/issues/11 – EL_DON May 22 '18 at 04:50
0

This can be done by

  1. Creating a global list of tracked windows
  2. Subclassing pg.GraphicsWindow or pg.PlogWidget (assuming you import pyqtgraph as pg)
  3. Adding newly created instances of the subclassed window/widget to the global tracking list
  4. Overriding closeEvent so it removes windows from the tracker when they are closed.

This works because of the way python caches imported modules, so importing tracking.tracker again should access the same variable.

For example: make tracking.py:

import warnings


class WTracker:

    def __init__(self):
        self.open_windows = []

    def window_closed(self, win):
        if win in self.open_windows:
            self.open_windows.remove(win)
        else:
            warnings.warn('  tracker received notification of closing of untracked window!')

    def window_opened(self, win):
        self.open_windows += [win]


tracker = WTracker()

And then figure.py:

import pyqtgraph as pg
from tracking import tracker


class Figure(pg.GraphicsWindow):
    def __init__(self):
        super(Figure, self).__init__()
        tracker.window_opened(self)

    def closeEvent(self, event):
        tracker.window_closed(self)
        event.accept()

Finally, we can implement gcf(); let's put it in pyplot.py:

from tracking import tracker
from figure import Figure


def gcf():
    if len(tracker.open_windows):
        return tracker.open_windows[-1]
    else:
        return Figure()

Then test with tester.py:

import sys
from PyQt4 import QtGui
from figure import Figure
from pyplot import gcf

app = QtGui.QApplication(sys.argv)

fig1 = gcf()
fig2 = gcf()
fig3 = Figure()
fig4 = gcf()
fig4.close()
fig5 = gcf()

print('fig2 is fig1 = {}'.format(fig2 is fig1))
print('fig3 is fig1 = {}'.format(fig3 is fig1))
print('fig4 is fig3 = {}'.format(fig4 is fig3))
print('fig5 is fig3 = {}'.format(fig5 is fig3))
print('fig5 is fig1 = {}'.format(fig5 is fig1))

The result:

$ python tester.py
fig2 is fig1 = True
fig3 is fig1 = False
fig4 is fig3 = True
fig5 is fig3 = False
fig5 is fig1 = True

Subclassing pg.PlotWidget instead of pg.GraphicsWindow works, but then you have to create a layout, set it as the central item, and run self.show().

EL_DON
  • 1,416
  • 1
  • 19
  • 34