When I create a custom applet to plot datasets using Matplotlib with Qt5Agg as the backend, I get an error processing data from the applet as follows:

ERROR:dashboard:artiq.gui.applets:error processing data from applet, server stopped
Traceback (most recent call last):
  File "C:\Users\<USERNAME>\anaconda3\envs\artiq\lib\site-packages\artiq\gui\applets.py", line 57, in serve
    obj = await self.read_pyon()
  File "C:\Users\<USERNAME>\anaconda3\envs\artiq\lib\site-packages\artiq\gui\applets.py", line 34, in read_pyon
    return pyon.decode(line.decode())
  File "C:\Users\<USERNAME>\anaconda3\envs\artiq\lib\site-packages\sipyco\pyon.py", line 210, in decode
    return eval(s, _eval_dict, {})
  File "<string>", line 0

    ^
SyntaxError: unexpected EOF while parsing

The applet command issued through the dashboard is: python "<PATH>\plot_experiment_data.py"

The code for the custom applet in plot_experiment_data.py is as follows:

import matplotlib
import matplotlib.pyplot as plt

from PyQt5 import QtWidgets
from artiq.applets.simple import SimpleApplet
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg

matplotlib.use('Qt5Agg')


class MplCanvas(FigureCanvasQTAgg):

    def __init__(self):
        fig, ax = plt.subplots()
        self.axes = ax
        super(MplCanvas, self).__init__(fig)


class ExperimentWidget(QtWidgets.QMainWindow):
    def __init__(self, args):
        super().__init__()

        self.sc = MplCanvas()
        self.setCentralWidget(self.sc)
        self.sc.axes.spines['left'].set_position('center')
        self.sc.axes.spines['right'].set_color('none')
        self.sc.axes.spines['bottom'].set_position('center')
        self.sc.axes.spines['top'].set_color('none')
        plt.grid(True)

    def data_changed(self, data, mods):
        self.sc.axes.plot(data['xs'][1], data['sine'][1])
        plt.show()


def main():
    applet = SimpleApplet(ExperimentWidget)
    applet.run()


if __name__ == "__main__":
    main()

I couldn't glean much about this from the examples provided in ARTIQ, so I'm stuck as to how I can resolve this issue.

Try to get more of the error message and/or run the applet standalone (outside the GUI), which is supported directly by artiq.applets.simple.
I assume from C:\...\anaconda3\... that you are using Windows and conda, correct?

    I've posted the full error message as it appears in the logs on the ARTIQ dashboard. When the applet is invoked from the dashboard, it shows up the Matplotlib plot for a fraction of a second and then crashes due to this error.

    WIPM/APM also have Matplotlib applets running:

    There should be a more complete error message somewhere...

    Note that Matplotlib is very slow.

    Ok, after seeing your screenshot, I ran artiq_browser and the application crashed with the following error when I opened up the h5 file corresponding to the experiment:

    WARNING:browser:artiq.browser.files:unable to read metadata from C:/Users/<USERNAME>/PycharmProjects/artiq-experiments/results/2020-12-14/17/000000039-TrigEnvironment.h5
    Traceback (most recent call last):
      File "C:\Users\<USERNAME>\anaconda3\envs\artiq\lib\site-packages\artiq\browser\files.py", line 177, in list_current_changed
        expid = pyon.decode(f["expid"].value)
    AttributeError: 'Dataset' object has no attribute 'value'
    Traceback (most recent call last):
      File "C:\Users\<USERNAME>\anaconda3\envs\artiq\lib\site-packages\artiq\browser\files.py", line 199, in list_current_changed
        rd[k] = (True, v.value)
    AttributeError: 'Dataset' object has no attribute 'value'

    I inspected the h5 file using the h5py library and it seems like f["expid"] is a HDF5 dataset object and HDF5 dataset objects do not have a value attribute.

    Suggestions that work for us to create the complex GUI:

    • we didn't use matplotlib.backends.backend_qt5agg directly. Instead, we made some nice GUI using QT designer (get a .ui file), and then generate a GUI_widget (a .py file) using PyQt generator. This GUI_widget is a QtWidgets
    • Then, we create a new class (say, Main_GUI) that inherit from that GUI_widget. All the actions like pressing buttons are defined here. This Main_GUI can be tested stand alone like all other Qt applications.
    • An applet that will be called by the ARTIQ is then inherit from this GUI_widget, with an additional function data_changed that talks with the datasets.

    To me, it seems that your code will try to create a new, standalone GUI (the MplCanvas) in the __init__ function. Standalone means you will have an empty QMainWindow at the beginning, and then another tiny window pops out. Then when data_changed, the QMainWindow tries to control the behavior of the other window.

    I'm not good at Qt programming, but this looks unusual to me.

    @Kaifeng, in the end that's what I ended up doing by emulating the custom_applet.py and code_applet.py examples in ARTIQ and using pyqtgraph. I suppose it could work with matplotlib as well. Thank you for suggestions!