GUI Science

There comes a point in every software-inclined lab based grad student’s life, where they think: now is the time to write a GUI for my software, to make it fast, easy to use, generalised so that others will use it too, the new paradigm for how to do research, etc. etc.

Of course such delusions of grandeur are rarely indulged, but when executed they certainly can produce useful outputs, as a well designed (or even, designed) GUI can improve an experimentalist’s life profoundly by simplifying, automating and standardising data acquisition, and by reducing the time to see results, allowing for shorter iteration cycles (this is known in engineering as “Design, Build, Test, Learn” cycle, in software it’s called “Coding”).

Having written a few GUIs in my time, I thought it might be helpful to share some experience I have, though it is by no means broad.

  1. If there already exists a GUI for what you want, at least try to use it first. While developing a GUI can lead to a small publication, ultimately it’s not “interesting” science, there’s no point re-inventing the wheel, especially as the existing wheel is likely far more polished and aerodynamic. In ML, there are a whole host of ready to go visualisation tools, ranging from Jupyter notebook, TensorBoard, Weights and Biases, etc. It is probably rare that a straight ML tool needs more than a CLI for good usability, but in the case where it does Ipywidgets is a good starting point.
  2. Don’t use LabVIEW unless you have to. If you have access to it, LabVIEW is fast to prototype, but ultimately results in an unmanageable mess. Others may learn how to work with your “code”, but many hours will have been wasted compared to a python script. That said, if you do use LabVIEW, then it is important to remember you are still developing software, and there are design principles which can make your software better. For instance, if you have processes which might take a while that you do not want to interrupt data acquisition, the producer-consumer pattern might be for you.
  3. As mentioned above, people have thought about these problems! Almost all of them! Designing your software by thinking about issues such as blocking, synchronisation etc. up front can lead to a much more functional outcome. Personally I find I need to try and fail at building anything before I am ready to lessons such as this, perhaps you can be more pragmatic, but if not, be ready to research and learn after the first failure. The LabVIEW design patterns above can be translated to any other language, though there are probably guides specific to whichever language you are using.
  4. Web developers have thought about this! When I’m designing a GUI, I care that the camera needs to be triggered synchronously with the laser, and some image processing is going to occur that is computationally expensive and that I don’t want it to freeze the interface. When web developers make websites, they care that the user has a smooth experience, and that the ultra 4K image of the kitten they are loading doesn’t freeze up the “Buy Now!” conversion button they are relying on for $$ click through. Perhaps surprisingly, this means there is a lot of helpful writing out there from people with the latter issue (of which there ~27 million) helping those of us with the former (of which there are at absolute most ~1 million). So: seek out advice on how to engineer snappy GUIs, and be prepared that someone’s solution to writing a chatbot project may be just what you need.

At present, I am rebuilding a GUI for control of a high throughput directed evolution platform. Initially, we went with a PyQT implementation, which while somewhat functional requires overly complex code, and has a resulted in a fairly slow and buggy interface. Note this is not necessarily the fault of QT, more a reflection that it’s learning curve is sufficiently steep that it’s not a great choice for a PhD/postdoc side project. Instead, I’ve had a much better experience using another python package NiceGUI, in combination with asyncio and websockets. Architecturally, the NiceGUI server communicates with a Microscope server over a websocket, ensuring that any GUI related issues or freezing cannot interrupt the experiment (and vice-versa). By requiring the communication between the two to happen over a websocket, this helps ensure we can’t cheat (i.e. directly implement some hardware call on the GUI side). The GUI itself is a web-app, meaning many of the complexities we had to deal with using QT are simply handled by the browser. As a nice side benefit, the GUI can be updated in real-time (e.g. to change the styling or interface) without needing to reload the entire project, as the microscope server is unaffected. This is great for developing a user-friendly interface, beyond one that is just functional. Furthermore, if we ever want to replace NiceGUI we can do so simply by implementing the same websocket API using a different framework.

Author