Question/Bug: matplotlib Qt backend specification
chrishavlin opened this issue · 4 comments
A question on yt slack reported the following error:
File ~/anaconda3/lib/python3.11/site-packages/yt/visualization/base_plot_types.py:137, in PlotMPL.__init__(self, fsize, axrect, norm_handler, figure, axes)
134 self.axes = axes
135 self.interactivity = get_interactivity()
--> 137 figure_canvas, figure_manager = self._get_canvas_classes()
138 self.canvas = figure_canvas(self.figure)
139 if figure_manager is not None:
TypeError: cannot unpack non-iterable NoneType object
The selected matplotlib backend in this instance is QtAgg
(found with import matplotlib; print(str(matplotlib.get_backend())
), so I think because yt's BACKEND_SPECS
only contains explicitly versioned Qt entries as keys:
yt/yt/visualization/base_plot_types.py
Lines 52 to 53 in d046de2
_get_canvas_classes
is catching a KeyError and returning None
, resulting in the above TypeError
:
yt/yt/visualization/base_plot_types.py
Lines 152 to 161 in d046de2
According to https://matplotlib.org/stable/api/backend_qt_api.html, specifying specific Qt backends is now discouraged, so I'm thinking BACKEND_SPECS
needs a new QtAgg
entry. Also looks like Qt4 support was dropped in matlab 3.5.0 (https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.5.0.html#qt-backends) and 3.5.0 is currently the minimum version for yt so I think we can just replace those 2 lines with a single QtAgg
line? That all sound sensible? I'm not super familiar with backends, so wanted to check before getting too deep...
Is it necessary to specify a backend in general? I've heard matplotlib isn't great at finding defaults, but I know I've had to change the backend through an environment variable on at least one system to get (interactive?) plotting to work at all. If setting the backend explicitly is not necessary, maybe it would be better to let users set this if they have to, based on what works/is available on their system.
Well it already is possible for the user to set the matplotlib backend, but internally yt tries to do its own detection in order to get the proper canvas objects (based on whatever matplotlib detects). It may be that this whole architecture could be removed or refactored, but I think that'd be a much larger refactor (throughout many of the yt plot window classes) compared to just getting the generic QtAgg backend to work.
BACKEND_SPECS
should definitely be updated in this situation. What I don't understand is why 4-years-ago me thought it was a good idea to silently swallow KeyError
s and return None
... Seeing that this does causes issues, I would suggest to just drop the try/except logic.
Ok, great. Thanks for the confirmation, @neutrinoceros . And I can push up a fix later today -- I spent some time yesterday experimenting with the qt back end options in new environments and I understand it much better now.