twibiral / obsidian-execute-code

Obsidian Plugin to execute code in a note.
MIT License
1.09k stars 66 forks source link

[BUG] Plot embed does not work if plt.show is not called directly from the code block #207

Open kjczarne opened 1 year ago

kjczarne commented 1 year ago

Hi,

I've noticed that the plugin seems to use the agg backend whenever I use a library like sympy and use the plotting facilities from there.

For example, the following code works perfectly:

import matplotlib as mpl
import matplotlib.pyplot as plt
fig, ax = plt.subplots()  # Create a figure containing a single axes.
ax.plot([1, 2, 3, 4], [1, 4, 2, 3]);  # Plot some data on the axes.
plt.show()

But the following does not:

from sympy import Piecewise, Lt, Le, symbols, plot
import matplotlib

x, a, b = symbols("x a b")
p = Piecewise((0, Lt(x, a)),
              (0, Lt(b, x)),
              (1 / (b-a), True))

plot(p.subs({"a": 3, "b": 5}))

I am getting:

/Users/user/Library/Python/3.9/lib/python/site-packages/sympy/plotting/plot.py:1555: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
  self.plt.show()

It seems like a bug to me although I'm open to workarounds.

Thanks for creating this plugin, it's on a great way towards cutting out Jupyter Notebooks from my workflow in favor of Obsidian!

kjczarne commented 1 year ago

Ok, I've found a workaround for sympy which relies on not showing the figure and calling plt.show() explicitly:

fig = plot(p.subs({"a": 3, "b": 5}), show=False)
plt.show()

This is a workaround. I am wondering if I'm missing some detail here. 🙂

twibiral commented 1 year ago

Hi @kjczarne, this feature only works if you try to show the plot via plt.show() as it searches through your code, generates an image and embeds the image in the note. It doesn't work if you call another method

kjczarne commented 1 year ago

Hi @twibiral, got it, thanks for the clarification. Feel free to close the issue if there are no plans to implement support for other functions that call plt.show() underneath. 🙂

twibiral commented 1 year ago

@kjczarne it's hard to implement this in a reliable way for all functions that are named plot(). We will maybe consider this sometime in the future