This answer reports the best solution I found so far, I'll be happy to hear from feedback or better alternatives:
I wanted to integrate matplotlib into Blender in its own space, but sadly learned that the Blender 2.80 API can't (yet) create new space types.
Therefore the solution for me was to let Blender's Python3.7 interpreter run a separate matplotlib window in a child process (see image).
For that, I had to do the following things:
Make sure import tkinter
works (here how I did it, no root privileges needed). With that, it should be possible to <BLENDERS_PYTHON> -m pip install matplotlib
and import it. Note that running matplotlib in plt.ioff()
mode blocked Blender, and running it in .ion()
mode did nothing. Running it on a child process solved it for me.
Make sure multiprocessing.Queue()
can be instantiated (In my Ubuntu17 system, this required to copy the _multiprocessing.so
file from my non-Blender lib-dynload
Python environment.
Now running the following from the Blender interpreter should spawn a child process, that interactively reacts to any changes that the Blender user makes to queue
:
import matplotlib.pyplot as plt
import multiprocessing as mp
import numpy
def worker(q):
fig=plt.figure()
ax=fig.add_subplot(111)
ln, = ax.plot([], [])
fig.canvas.draw() # draw and show it
plt.show(block=False)
i = 0
while True:
obj = q.get()
n = obj + 0
print("sub : got:", n)
lnx, lny = ln.get_xdata(), ln.get_ydata()
ln.set_xdata(numpy.append(lnx, i))
ln.set_ydata(numpy.append(lny, n))
ax.relim()
ax.autoscale_view(True,True,True)
fig.canvas.draw()
i += 1
queue = mp.Queue()
p = mp.Process(target=worker, args=(queue,))
p.start()
Once the window is open and listening, add entries to the plot, for example like this:
queue.put(bpy.context.scene.frame_current)
The new entry will be interactively incorporated to the plot. Once you are done, simply kill the process with:
p.terminate()
Hope this helps!
Cheers,
Andres