matplotlib-pyodide
matplotlib-pyodide copied to clipboard
plotting fails with `document.pyodideMplTarget` set
I attempted to use document.pyodideMplTarget to set a target element for a plot, and obtained this error message:
File "<exec>", line 59, in tplot
File "/lib/python3.11/site-packages/matplotlib/pyplot.py", line 389, in show
return _get_backend_mod().show(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/lib/python3.11/site-packages/matplotlib_pyodide/html5_canvas_backend.py", line 450, in show
plt.gcf().canvas.show()
File "/lib/python3.11/site-packages/matplotlib_pyodide/browser_backend.py", line 117, in show
div = self._create_root_element()
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/lib/python3.11/site-packages/matplotlib_pyodide/browser_backend.py", line 317, in _create_root_element
mpl_target.appendChild(div)
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'appendChild'
M https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
new_error https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
_pythonexc2js https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
callPyObjectKwargs https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
callPyObject https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
apply https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
apply https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.asm.js:9
replot http://localhost:8000/lumped_capacitance.html:98
async* http://localhost:8000/lumped_capacitance.html:103
EventListener.handleEvent* http://localhost:8000/lumped_capacitance.html:102
I've attached my html code for this error. For now, I'm just using the default append behavior. lumped_capacitance.html.txt
Ok, I fixed the plotting fail by waiting for DOMContentLoaded before setting document.pyodideMplTarget.
Now, plotting works but the target div is not reused and I still get the default append behavior. html attached.
Now, plotting works but the target div is not reused and I still get the default append behavior. html attached.
The target div is used, but what happens is that it does not clean up the old plot when showing a new plot. There is an open issue about this behavior (https://github.com/pyodide/matplotlib-pyodide/issues/49).
Due to the lack of manpower, this repository is not actively maintained, so I would appreciate it if you could contribute to this. I think @yu0A is working on this issue too.
FigureCanvasBase and child FigureCanvas of Matplotlib cannot be reused. It is like, you should call pyplot.close() method or manually close picture viewer generated by Python if you call pyplot.show() method on Windows env. So my way is manually call pyplot.close() method to destroy old FigureCanvas (divs).
FigureCanvasBase and child FigureCanvas of Matplotlib cannot be reused. It is like, you should call pyplot.close() method or manually close picture viewer generated by Python if you call pyplot.show() method on Windows env. So my way is manually call pyplot.close() method to destroy old FigureCanvas (divs).
When I call pyplot.close() method, due to FigureCanvas should realize destroy() method, I'm working on this method.
Have you ever got to rendering plot in a custom div?
This is what I got and I always see the div attached to the end:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js"></script>
</head>
<body>
<div id="app">
<canvas id="target" width="400" height="400"></canvas>
</div>
<script src="./index.js"></script>
</body>
</html>
And js:
async function main() {
let pyodide = await loadPyodide();
document.pyodideMplTarget = document.getElementById("target");
await pyodide.loadPackage("matplotlib");
pyodide.runPython(`
import matplotlib
matplotlib.use("module://matplotlib_pyodide.html5_canvas_backend")
import matplotlib.pyplot as plt
import numpy as np
# matplotlib.use("module://matplotlib.backends.html5_canvas_backend")
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
`);
}
main();
The wasm backend never works
Have you ever got to rendering plot in a custom div? The new divs really generates as children of div id="target". you can find the div id="target" in my code.
This is what I got and I always see the div attached to the end:
That's the problem. The "module://matplotlib_pyodide.html5_canvas_backend" only generates divs in <div></div> tags.
Try to change your html to <div id="target" style="width:400px; height:400px;"></div>
Hello, no love for me. I did change the source as you described but still getting the result ina separate div:
Hello, no love for me. I did change the source as you described but still getting the result ina separate div:
I give my development html project to you. In my project the divs can always generate under the target div, and supports manually show and close figure.
This project is for you