pypulseq
pypulseq copied to clipboard
PyQt5 requirement for Ubuntu/Linux systems
Describe the bug seq.plot() does not display graphs
To Reproduce On Ubuntu 22.04. LTS run write_gre.py with plot=True
Expected behavior No plot shows
Screenshots NA
Desktop (please complete the following information):
- OS: Ubuntu
- OS Version: 22.04. LTS
pypulseqversion: 1.4.2
Additional context Adding PyQt5 package solves the issue.
This is more relevant to Matplotlib rather than PyPulseq. Matplotlib supports many "backends", PyQt5 is just one of them. Users should be able to pick whichever backend they want. Most Python installations come with Tkinter, so plots should be able to shown without installing any additional dependency using Tkinter.
Documentation showing how to configure backends: https://matplotlib.org/stable/users/explain/figure/backends.html
If you configure matplotlib to use TkAgg using any of the recommended configuration options, you should be able to see the plots without installing PyQt.
That sounds like a good idea. If you don't want to make the env heavy then it is best to introduce an argument for the mpl_backend in the seq.plot() definition.
def plot( self, label: str = str(), show_blocks: bool = False, save: bool = False, time_range=(0, np.inf), time_disp: str = 's', grad_disp: str = 'kHz/m', plot_now: bool = True, mpl_backend = 'default_method', ) -> None:
Implement using matplotlib.use(
The consequence of not handling via a package or the mpl_backend argument is code breaking (read as no plots displayed when plot=True). Any other alternate is fine too, just want to make sure that the code does not break for these different scenarios.
I looked into this some time ago. I checked projects that are dealing with matplotlib as well. I could not see a nice way of handling this, without forcing a specific backend.
I don't think calling use() inside plot() is a good solution. If the user or calls a plot with a different backend then default_method before calling our plot() function, it will also cause an error. Automatically setting a sane backend is already being done by matplotlib, and it usually fails when there is no available one, so I don't see how we can improve on that.
These are the two potential solutions I can think of:
- We can provide an optional dependency on
PySide6onpyproject.toml, then someone can install viapip install pypulseq[Qt], for example, it will ensure an interactive backend is available. - We can check if the active backend is non-interactive and print a warning (I believe matplotlib already should print such a warning, but in case it is not clear):
import matplotlib
current_backend = matplotlib.get_backend()
print(f"Current Matplotlib backend: {current_backend}")
non_interactive_backends = ['agg', 'pdf', 'ps', 'svg', 'cairo']
if current_backend.lower() in non_interactive_backends:
print("A non-interactive backend is currently selected.")
else:
print("An interactive backend is currently selected.")
#323 might be a good PR to add this check.
I feel like this is a more common problem nowadays because distros are dropping Tkinter from their Python distributions.