Skip to content

Commit bec2b4e

Browse files
committed
fix matplotlib graphs sometimes not rendering
1 parent 99e807a commit bec2b4e

File tree

3 files changed

+25
-19
lines changed

3 files changed

+25
-19
lines changed

src/ogdf_python/matplotlib/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@
2020

2121

2222
def repr_mimebundle_GraphAttributes(self, *args, **kwargs):
23-
fig = new_figure()
24-
ax = fig.subplots()
25-
fig.graph = MatplotlibGraph(self, ax)
26-
return fig.graph._repr_mimebundle_(*args, **kwargs)
23+
return MatplotlibGraph(self)._repr_mimebundle_(*args, **kwargs)
2724

2825

2926
def repr_mimebundle_Graph(self, *args, **kwargs):
@@ -40,3 +37,9 @@ def repr_mimebundle_ClusterGraph(self, *args, **kwargs):
4037
ogdf.Graph._repr_mimebundle_ = repr_mimebundle_Graph
4138
ogdf.ClusterGraphAttributes._repr_mimebundle_ = repr_mimebundle_GraphAttributes
4239
ogdf.ClusterGraph._repr_mimebundle_ = repr_mimebundle_ClusterGraph
40+
41+
# ensure that backend is loaded and doesn't reset any configs (esp. is_interactive)
42+
# when being loaded for the first time
43+
import matplotlib.pyplot as plt
44+
45+
plt.close(new_figure())

src/ogdf_python/matplotlib/util.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -326,24 +326,20 @@ def find_closest(GA, x, y, edge_dist=10):
326326
return None, None, None
327327

328328

329-
def new_figure(num=None) -> Figure:
329+
def new_figure(*args, **kwargs) -> Figure:
330+
""" Create a new figure without changing the currently active figure of pyplot """
330331
import matplotlib.pyplot as plt
331332
from matplotlib import _pylab_helpers
332-
with plt.ioff():
333+
plt._get_backend_mod() # make sure backend is loaded before ioff call
334+
with plt.ioff(): # disable immediate display of created figures
333335
old_fig = None
336+
# like plt.gcf(), but does not create one if none is active
334337
manager = _pylab_helpers.Gcf.get_active()
335338
if manager is not None:
336339
old_fig = manager.canvas.figure
337340

338-
fig = plt.figure(num)
341+
fig = plt.figure(*args, **kwargs)
339342

340343
if old_fig is not None:
341-
plt.figure(old_fig)
344+
plt.figure(old_fig) # reactivate the old figure
342345
return fig
343-
344-
345-
# ensure that backend is loaded and doesn't reset any configs (esp. is_interactive)
346-
# when being loaded for the first time
347-
import matplotlib.pyplot as plt
348-
349-
plt.close(new_figure())

src/ogdf_python/matplotlib/widget.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import functools
2+
import sys
23
import traceback
4+
from itertools import chain
35
from typing import Dict, Tuple, List
46

57
import numpy as np
6-
import sys
7-
from itertools import chain
88
from matplotlib import patheffects
99
from matplotlib.axes import Axes
1010
from matplotlib.backend_bases import MouseButton
@@ -200,17 +200,24 @@ def _repr_mimebundle_(self, *args, **kwargs):
200200
if not InteractiveShell.initialized():
201201
return {"text/plain": repr(self)}, {}
202202

203+
# larger graphs (see eg `tutorial/4 layouts.ipynb`) sometimes render blank
204+
# ensure they are drawn first and spinning the event loop for some time makes that less likely
205+
self.ax.figure.canvas.draw()
206+
self.ax.figure.canvas.start_event_loop(0.1)
207+
203208
fmt = InteractiveShell.instance().display_formatter
209+
# if ipython_display_formatter is enabled, format(figure.canvas) immediately displays and returns None
204210
display_en = fmt.ipython_display_formatter.enabled
205211
fmt.ipython_display_formatter.enabled = False
206212
try:
213+
# for interactive backends, we want to render the interactive figure.canvas widget
207214
data, meta = fmt.format(self.ax.figure.canvas, *args, **kwargs)
208-
# print("canvas", list(data.keys()) if data else "none")
215+
# for non-interactive backends, this only renders the text/plain repr()
209216
if list(data.keys()) != ["text/plain"] and data:
210217
return data, meta
211218
else:
219+
# so we render the figure instead, which gives a static image
212220
data, meta = fmt.format(self.ax.figure, *args, **kwargs)
213-
# print("figure", list(data.keys()) if data else "none")
214221
return data, meta
215222
finally:
216223
fmt.ipython_display_formatter.enabled = display_en

0 commit comments

Comments
 (0)