-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Documentation and bug report: mplot3d and blitting #27830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think the main issue is that the Line3D object was never added to the
axes object. It can't draw an object it doesn't "own". Here is an example
(albeit without blitting):
https://matplotlib.org/stable/gallery/animation/random_walk.html
…On Wed, Feb 28, 2024 at 6:06 AM Fcp-GitHub ***@***.***> wrote:
Bug summary Summary
Problem with 3d animation using FuncAnimation and the mplot3d toolkit.
Maybe this problem comes from not enough clarifications in the
documentation. Following this it is presented a simplified version of the
program that led me to these conclusions.
Explanation
Looking through the documentation regarding animation and blitting, it is
possible to see two different approaches:
- The first one (see here
<https://matplotlib.org/stable/users/explain/animations/animations.html#funcanimation>)
is presented at the first explanation page about creating animations with
the animation module. Here it is explained that in the function passed
to FuncAnimation there has to be some method that updates the data in
each artist in order to generate the new frame. It is written that "the
update function uses the set_* function for different artists to
modify the data".
- However, the second approach (presented here
<https://matplotlib.org/stable/users/explain/animations/blitting.html#sphx-glr-users-explain-animations-blitting-py>,
where blitting is actually explained) tells the user to use the
draw_artist() method in order to update/redraw efficiently the artists
in the function of the render loop. I haven't found many low-level details
(except some look directly at the source code) about the functioning of
FuncAnimation or plt.show(), so I couldn't make real assumptions about
their involvement in this.
Mixing the informations, I have encountered many problems that I will try
to replicate and explain in the following code.
Code for reproduction
import matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d.art3d import Line3Dfrom matplotlib.animation import FuncAnimation
fig = plt.figure()ax = fig.add_subplot(projection='3d', xlim=(0,100), ylim=(0,100), zlim=(0,100))
line = Line3D( [0], [0], [0], marker="o", markersize=15, color='r', animated=True)
def update(t):
line.set_data_3d([t],[t],[t])
ax.draw_artist(line)
return line,
anim = FuncAnimation(fig=fig, func=update, frames=None, blit=True, cache_frame_data=False)
plt.show()
Actual outcome
File "C:\Users\user\Desktop...\axes3d_issue.py", line 13, in update
ax.draw_artist(line)
File
"C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\axes_base.py",
line 3080, in draw_artist
a.draw(self.figure.canvas.get_renderer())
File
"C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\artist.py",
line 72, in draw_wrapper
return draw(artist, renderer)
^^^^^^^^^^^^^^^^^^^^^^
File
"C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\mpl_toolkits\mplot3d\art3d.py",
line 270, in draw
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'M'
Expected outcome
The rendering of the image.
Additional information
Some considerations:
1. Maybe the draw_artist() method should be used in combination with
plt.pause() or by API developers, but neither is specified in the
documentation. Removing the ax.draw_artist(line) (following thus the
first approach described at the beginning) is indeed a solution to the
problem.
2. Using Visual Studio Code Data inspection debug tool along with
debugpy, I've noticed that in the update() function the Line3D artist
seems to lose all the references to the parent classes Axes3D and
Figure, hence some error messages. However, trying to add something
like line.axes = ax leads directly to an exception raised due to the
next problem.
3. It seems that without calling the 'Axes3D.draw()' method first, the
projection matrix variable M of the same class is never updated from
None to some value. Actually, calling the Axes3D.get_proj() method for
M and computing the inverse matrix also for the invM attribute seems
to work. This appears to be a flaw in every case, but maybe it corroborates
the hypothesis of some kind of "reservedness" of the method for some
special cases.
If this is the case, it is not specified neither in the already cited
documentation, neither in the (quite short, for some reason) mplot3d
documentation (see here
<https://matplotlib.org/stable/users/explain/toolkits/mplot3d.html>).
I think the documentation about this topic should be a bit clearer. Some
more explanation about the inner working of some ubiquitous functions like
plt.show() or the clear methods, another set of functions that is
presentend unclearly, could help users understand and resolve their
problems, along with using them more consciously.
Operating system
Microsoft Windows 11 Home
Matplotlib Version
3.8.2
Matplotlib Backend
TkAgg
Python version
3.12.2
Jupyter version
*No response*
Installation
pip
—
Reply to this email directly, view it on GitHub
<#27830>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACHF6FG7RFQMJ26CP6Q4ETYV4FTHAVCNFSM6AAAAABD5ZVPF2VHI2DSMVQWIX3LMV43ASLTON2WKOZSGE2TQNZQGA3DGNY>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
I'll note that this example is probably about 10 years old, and the claim
that "set_data()" for 3D data is no longer true, as your example
demonstrates.
…On Wed, Feb 28, 2024 at 10:31 AM Benjamin Root ***@***.***> wrote:
I think the main issue is that the Line3D object was never added to the
axes object. It can't draw an object it doesn't "own". Here is an example
(albeit without blitting):
https://matplotlib.org/stable/gallery/animation/random_walk.html
On Wed, Feb 28, 2024 at 6:06 AM Fcp-GitHub ***@***.***>
wrote:
> Bug summary Summary
>
> Problem with 3d animation using FuncAnimation and the mplot3d toolkit.
> Maybe this problem comes from not enough clarifications in the
> documentation. Following this it is presented a simplified version of the
> program that led me to these conclusions.
> Explanation
>
> Looking through the documentation regarding animation and blitting, it is
> possible to see two different approaches:
>
> - The first one (see here
> <https://matplotlib.org/stable/users/explain/animations/animations.html#funcanimation>)
> is presented at the first explanation page about creating animations with
> the animation module. Here it is explained that in the function
> passed to FuncAnimation there has to be some method that updates the
> data in each artist in order to generate the new frame. It is written that
> "the update function uses the set_* function for different artists to
> modify the data".
> - However, the second approach (presented here
> <https://matplotlib.org/stable/users/explain/animations/blitting.html#sphx-glr-users-explain-animations-blitting-py>,
> where blitting is actually explained) tells the user to use the
> draw_artist() method in order to update/redraw efficiently the
> artists in the function of the render loop. I haven't found many low-level
> details (except some look directly at the source code) about the
> functioning of FuncAnimation or plt.show(), so I couldn't make real
> assumptions about their involvement in this.
>
> Mixing the informations, I have encountered many problems that I will try
> to replicate and explain in the following code.
> Code for reproduction
>
> import matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d.art3d import Line3Dfrom matplotlib.animation import FuncAnimation
> fig = plt.figure()ax = fig.add_subplot(projection='3d', xlim=(0,100), ylim=(0,100), zlim=(0,100))
> line = Line3D( [0], [0], [0], marker="o", markersize=15, color='r', animated=True)
> def update(t):
> line.set_data_3d([t],[t],[t])
> ax.draw_artist(line)
>
> return line,
> anim = FuncAnimation(fig=fig, func=update, frames=None, blit=True, cache_frame_data=False)
> plt.show()
>
> Actual outcome
>
> File "C:\Users\user\Desktop...\axes3d_issue.py", line 13, in update
> ax.draw_artist(line)
> File
> "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\axes_base.py",
> line 3080, in draw_artist
> a.draw(self.figure.canvas.get_renderer())
> File
> "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\artist.py",
> line 72, in draw_wrapper
> return draw(artist, renderer)
> ^^^^^^^^^^^^^^^^^^^^^^
> File
> "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\mpl_toolkits\mplot3d\art3d.py",
> line 270, in draw
> xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
> ^^^^^^^^^^^
> AttributeError: 'NoneType' object has no attribute 'M'
> Expected outcome
>
> The rendering of the image.
> Additional information
>
> Some considerations:
>
> 1. Maybe the draw_artist() method should be used in combination with
> plt.pause() or by API developers, but neither is specified in the
> documentation. Removing the ax.draw_artist(line) (following thus the
> first approach described at the beginning) is indeed a solution to the
> problem.
> 2. Using Visual Studio Code Data inspection debug tool along with
> debugpy, I've noticed that in the update() function the Line3D artist
> seems to lose all the references to the parent classes Axes3D and
> Figure, hence some error messages. However, trying to add something
> like line.axes = ax leads directly to an exception raised due to the
> next problem.
> 3. It seems that without calling the 'Axes3D.draw()' method first,
> the projection matrix variable M of the same class is never updated
> from None to some value. Actually, calling the Axes3D.get_proj()
> method for M and computing the inverse matrix also for the invM
> attribute seems to work. This appears to be a flaw in every case, but maybe
> it corroborates the hypothesis of some kind of "reservedness" of the method
> for some special cases.
> If this is the case, it is not specified neither in the already cited
> documentation, neither in the (quite short, for some reason) mplot3d
> documentation (see here
> <https://matplotlib.org/stable/users/explain/toolkits/mplot3d.html>).
>
> I think the documentation about this topic should be a bit clearer. Some
> more explanation about the inner working of some ubiquitous functions like
> plt.show() or the clear methods, another set of functions that is
> presentend unclearly, could help users understand and resolve their
> problems, along with using them more consciously.
> Operating system
>
> Microsoft Windows 11 Home
> Matplotlib Version
>
> 3.8.2
> Matplotlib Backend
>
> TkAgg
> Python version
>
> 3.12.2
> Jupyter version
>
> *No response*
> Installation
>
> pip
>
> —
> Reply to this email directly, view it on GitHub
> <#27830>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACHF6FG7RFQMJ26CP6Q4ETYV4FTHAVCNFSM6AAAAABD5ZVPF2VHI2DSMVQWIX3LMV43ASLTON2WKOZSGE2TQNZQGA3DGNY>
> .
> You are receiving this because you are subscribed to this thread.Message
> ID: ***@***.***>
>
|
Unfortunately, I won't be able to test the new results for some days. However, if I remember correctly, something was off in this case too. Thank you for your answer. |
Ok, I have added the |
If you use This works:
|
- use `set_data_3d` - cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata` - Rewrite parts of the FuncAnimation description Inspired through matplotlib#27830.
- use `set_data_3d` - cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata` - Rewrite parts of the FuncAnimation description Inspired through matplotlib#27830.
#27867 fixes some general documentation issues uncovered above. Still open: Better description of blitting in
|
Agreed. The I think there should also be some better documentation for |
- use `set_data_3d` - cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata` - Rewrite parts of the FuncAnimation description Inspired through matplotlib#27830.
- use `set_data_3d` - cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata` - Rewrite parts of the FuncAnimation description Inspired through matplotlib#27830.
pin pytest Deprecate plot_date Correctly set temporary pdf/pgf backends Calling `FigureCanvasPdf(figure)` will call `figure.set_canvas(self)`, meaning the `cbook._setattr_cm` context manager that wraps this change will see the _new_ canvas, and the old canvas isn't restored. Instead, just pass the `backend` parameter, as `savefig` already knows how to correctly save and restore the canvas if it needs to change backends. Fixes matplotlib#27865 Bump the actions group with 2 updates Bumps the actions group with 2 updates: [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) and [scientific-python/upload-nightly-action](https://github.com/scientific-python/upload-nightly-action). Updates `pypa/gh-action-pypi-publish` from 1.8.11 to 1.8.12 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](pypa/gh-action-pypi-publish@2f6f737...e53eb8b) Updates `scientific-python/upload-nightly-action` from 0.3.0 to 0.5.0 - [Release notes](https://github.com/scientific-python/upload-nightly-action/releases) - [Commits](scientific-python/upload-nightly-action@6e9304f...b67d7fc) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: scientific-python/upload-nightly-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com> Bump pydata-sphinx-theme to 0.15 Fix search button placement in navbar Fix doc sidebar Fix version switcher url for circleCI Don't use custom CSS for announcement banner Disable parallel build Don't show doc source link Add dtype/copy args to internal testing class Use pybind11 string formatter for exception messages This can eventually be replaced by `std::format` when we require C++20. doc: add description of **kwargs usage to collections (matplotlib#27872) * doc: add description of **kwargs usage to collections * Update lib/matplotlib/collections.py Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --------- Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> TST: adding tests of current clear behavior on ticks closes matplotlib#23839 DOC: update comments and docstrings Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Update lib/matplotlib/tests/test_axes.py BLD,Cygwin: Included Python.h first in src/_c_internal_utils.cpp Python.h needs to be included before any system includes. This is easiest if it is the first include. Interestingly, pybind11/pybind11.h does not include Python, possibly depending on downstream projects including Python.h beforehand. CI: Include Python.h first in _tkagg.cpp Needs to be included before system headers to set visibility macros for pybind11 BLD: Include Python.h first in _backend_agg.cpp BLD: Include Python.h before pybind11/pybind11.h pybind11 assumes Python.h is included first. CI: Specify python version for default pytest. CI,Cygwin: Run pytest with python -m pytest Cygwin pytest recently updated, and only installs pytest-3.9 CI,Cygwin: Revert use of alternatives to set pytest script. Cygwin pytest only installs pytest-3.9. I should possibly suggest using alternatives for that and pip. CI,Cygwin: Avoid running pytest in root directory. CI,Cygwin: Revert running pytest in different directory. CI,Cygwin: Call pytest-3.9 explicitly. BLD: Include Python.h first in src/_path.h BLD,BUG: Remove Python.h includes immediately preceeding pybind11/pybind11.h includes pybind11 seems decent about including Python.h before any system headers, once you chase three layers of includes in to see that. FIX: handle nans in RGBA input with ScalarMappables DOC: Update some animation related topics - use `set_data_3d` - cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata` - Rewrite parts of the FuncAnimation description Inspired through matplotlib#27830. Revert "Merge branch 'matplotlib:main' into doc-change" This reverts commit feeabe6, reversing changes made to bcbc2ef. Reapply "Merge branch 'matplotlib:main' into doc-change" This reverts commit ed91cee. Convert path extension to pybind11 Add a pybind11 type caster for agg::rect_d Add a pybind11 type caster for agg::trans_affine Add a pybind11 type caster for mpl::PathIterator Add a pybind11 type caster for e_snap_mode Add a pybind11 type caster for SketchParams Optimize convert_polygon_vector a bit FIX: don't copy twice on RGB input Fix devdocs version switcher Allow passing a transformation to secondary_[xy]axis Add transform argument to secondary axes Update _secax_docstring Move new params to end of functions Add input check to secondary axes Add tests Add examples Move transform type checks and improve docs Add type stubs Update _secax_docstring Move new params to end of functions Add input check to secondary axes Move transform type checks and improve docs Fix rebase error Fix stub for SecondaryAxis.__init__ Clarify example Add default param to secax constructor Fix stub for secax constructor Simplify imports Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com> Remove redundancy in docs Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com> Fix typo DOC: fix stray release note entry BLD: Add a fallback URL for FreeType FreeType is available from both Savannah and SourceForge, and sometimes AppVeyor seems to have trouble downloading from Savannah, so perhaps this fallback will help. We used to try both these URLs in the pre-Meson build system. DOC: State approximate documentation build time Since the doc build takes very long, an order-of-magnitude estimate is helpful to manage expectations. I'm not wedded to the actual numbers, if somebody has better suggestions. A quick test on an old i7 6700 (from 2015) yielded - `O=-j1`: 23min - `O=-j4`: 15min Doc build on CI is around 18min. Add BackendRegistry singleton class Use backend_registry for name of singleton instance Use class variables for immutable collections Review comments Update lib/matplotlib/backend_bases.py Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Linting/mypy fixes Remove INTERACTIVE_NON_WEB backend filter Small changes from review Use _api.caching_module_getattr for deprecated module-level attributes Add docstrings Add api changes and what new docs Fix docs Inline the deprecation function calls Import BackendFilter and backend_registry into matplotlib.backends.__init__.py Mypy fixes Remove unused _safe_pyplot_import Remove unneeded type annotations Make sure custom alpha param does not change 'none' colors in a list of colors (matplotlib#27845) * fix issue 27839, make sure alpha param does not affect none colors Apply review feedbacks Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> * Update lib/matplotlib/colors.py Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com> --------- Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com> DOC: fix :mpltype:`color` role `inline.interpreted()` already returns a list of nodes. We mustn't wrap it in another list. Use :mpltype:`color` for color types
Bug summary
Summary
Problem with 3d animation using
FuncAnimation
and themplot3d
toolkit. Maybe this problem comes from not enough clarifications in the documentation. Following this it is presented a simplified version of the program that led me to these conclusions.Explanation
Looking through the documentation regarding animation and blitting, it is possible to see two different approaches:
animation
module. Here it is explained that in the function passed toFuncAnimation
there has to be some method that updates the data in each artist in order to generate the new frame. It is written that "the update function uses theset_*
function for different artists to modify the data".draw_artist()
method in order to update/redraw efficiently the artists in the function of the render loop. I haven't found many low-level details (except some look directly at the source code) about the functioning ofFuncAnimation
orplt.show()
, so I couldn't make real assumptions about their involvement in this.Mixing the informations, I have encountered many problems that I will try to replicate and explain in the following code.
Code for reproduction
Actual outcome
File "C:\Users\user\Desktop...\axes3d_issue.py", line 13, in update
ax.draw_artist(line)
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\axes_base.py", line 3080, in draw_artist
a.draw(self.figure.canvas.get_renderer())
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\matplotlib\artist.py", line 72, in draw_wrapper
return draw(artist, renderer)
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\mpl_toolkits\mplot3d\art3d.py", line 270, in draw
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'M'
Expected outcome
The rendering of the image.
Additional information
Some considerations:
draw_artist()
method should be used in combination withplt.pause()
or by API developers, but neither is specified in the documentation. Removing theax.draw_artist(line)
(following thus the first approach described at the beginning) is indeed a solution to the problem.debugpy
, I've noticed that in theupdate()
function theLine3D
artist seems to lose all the references to the parent classesAxes3D
andFigure
, hence some error messages. However, trying to add something likeline.axes = ax
leads directly to an exception raised due to the next problem.M
of the same class is never updated fromNone
to some value. Actually, calling theAxes3D.get_proj()
method forM
and computing the inverse matrix also for theinvM
attribute seems to work. This appears to be a flaw in every case, but maybe it corroborates the hypothesis of some kind of "reservedness" of the method for some special cases.If this is the case, it is not specified neither in the already cited documentation, neither in the (quite short, for some reason)
mplot3d
documentation (see here).I think the documentation about this topic should be a bit clearer. Some more explanation about the inner working of some ubiquitous functions like
plt.show()
or theclear
methods, another set of functions that is presentend unclearly, could help users understand and resolve their problems, along with using them more consciously.Operating system
Microsoft Windows 11 Home
Matplotlib Version
3.8.2
Matplotlib Backend
TkAgg
Python version
3.12.2
Jupyter version
No response
Installation
pip
The text was updated successfully, but these errors were encountered: