Skip to content

[ENH] Implement dynamic clipping to axes limits for 3D plots #27349

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

Merged
merged 4 commits into from
Oct 2, 2024

Conversation

scottshambaugh
Copy link
Contributor

@scottshambaugh scottshambaugh commented Nov 20, 2023

Closes #25804

PR summary

This PR introduces "dynamic clipping" of the data in 3D plots, such that data outside the axis limits is not shown. I did a deep dive into stackoverflow and found 12 separate questions asking for this sort of functionality (see that list in this comment).

All 3D plotting functions now support the axlim_clip keyword argument (default False), which when True will clip the data to the axes view limits, hiding all data outside those bounds. This clipping will be dynamically applied in real time while panning and zooming.

Please note that if one vertex of a line segment or 3D patch is clipped, the entire segment or patch will be hidden. Not being able to show partial lines or patches such that they are "smoothly" cut off at the boundaries of the view box is a limitation of the current renderer.

What's new and new gallery example image (I'm not in love with this example, but it'll do for now):

3d_clip_to_axis_limits-1

Video of the dynamic behavior, please excuse my sluggish machine:

2023-11-25.22-47-45-1.mp4

PR checklist

@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 7 times, most recently from 74a0810 to 6bed144 Compare November 26, 2023 05:47
@scottshambaugh scottshambaugh marked this pull request as ready for review November 26, 2023 05:49
@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 2 times, most recently from 490ad58 to b73d8dc Compare November 26, 2023 06:08
@scottshambaugh scottshambaugh changed the title DRAFT: Implement dynamic clipping to axes limits for 3D plots [ENH] Implement dynamic clipping to axes limits for 3D plots Nov 26, 2023
@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 5 times, most recently from 674235d to faf74b6 Compare November 27, 2023 16:52
@scottshambaugh
Copy link
Contributor Author

Current test failures are due to minor pixel differences in the contours unrelated to this change, will keep tweaking until it passes.
image

@scottshambaugh
Copy link
Contributor Author

scottshambaugh commented Nov 27, 2023

TODO:

@scottshambaugh scottshambaugh marked this pull request as draft November 27, 2023 22:21
@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 2 times, most recently from b2a9978 to be117e7 Compare November 28, 2023 03:06
@scottshambaugh scottshambaugh marked this pull request as ready for review November 28, 2023 03:24
@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 2 times, most recently from 857252a to 8931e3a Compare November 28, 2023 05:18
@QuLogic
Copy link
Member

QuLogic commented Nov 28, 2023

Not being able to show partial lines or patches such that they are "smoothly" cut off at the boundaries of the view box is a limitation of the current renderer.

I don't think that's the case; we can definitely clip partial lines or patches to the Axes. Unless you mean the 3D renderer?

In that case, you would have to do some magic to calculate the clipping path of the Axes3D box with the artist in flattened 2D space, and apply it with set_clip_path. I'm not sure if that is worth it or not.

@scottshambaugh
Copy link
Contributor Author

Thank you for the review @QuLogic! I believe all your comments are addressed now

@scottshambaugh
Copy link
Contributor Author

The docs build error is unrelated:

The version switcher "https://output.circle-artifacts.com/output/job/29bcafd2-ffe3-4f64-ba51-f8cfa5bce2b5/artifacts/0/doc/build/html/_static/switcher.json" file cannot be read due to the following error:
HTTPError('404 Client Error: Not Found for url: https://output.circle-artifacts.com/output/job/29bcafd2-ffe3-4f64-ba51-f8cfa5bce2b5/artifacts/0/doc/build/html/_static/switcher.json')

@scottshambaugh
Copy link
Contributor Author

I think that the docs error isn't actually generic, will investigate.

@QuLogic
Copy link
Member

QuLogic commented Aug 23, 2024

/home/circleci/project/lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Poly3DCollection.set:45: WARNING: py:meth reference target not found: matplotlib.collections._CollectionWithSizes.set_sizes [ref.meth]

The missing reference handler is now a bit more specific about these things, so if you've added/removed some lines in a docstring, you may have to update the line numbers in the json file to get it to skip again.

@scottshambaugh
Copy link
Contributor Author

scottshambaugh commented Aug 24, 2024

This is a rather confusing error. It traces back to ./doc/missing-references.json, which has the below section:

"matplotlib.collections._CollectionWithSizes.set_sizes": [
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.barbs:179",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.broken_barh:84",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_between:120",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.fill_betweenx:120",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.hexbin:213",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.pcolor:182",
"lib/matplotlib/axes/_axes.py:docstring of matplotlib.axes._axes.Axes.quiver:215",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.AsteriskPolygonCollection.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.CircleCollection.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.PathCollection.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.PolyCollection.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.PolyQuadMesh.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.RegularPolyCollection.set:44",
"lib/matplotlib/collections.py:docstring of matplotlib.artist.StarPolygonCollection.set:44",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.barbs:179",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.broken_barh:84",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_between:120",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.fill_betweenx:120",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.hexbin:213",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.pcolor:182",
"lib/matplotlib/pyplot.py:docstring of matplotlib.pyplot.quiver:215",
"lib/matplotlib/quiver.py:docstring of matplotlib.artist.Barbs.set:45",
"lib/matplotlib/quiver.py:docstring of matplotlib.artist.Quiver.set:45",
"lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Barbs:212",
"lib/matplotlib/quiver.py:docstring of matplotlib.quiver.Quiver:251",
"lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Path3DCollection.set:46",
"lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Poly3DCollection.set:44"
],

... but set_sizes is not in the art3d.py.Poly3DCollection docstrings so I'm not sure how to adjust the numbering. Any pointers?

I did add 3 lines to the __init__() docstring, so will try adding 3 to each of these lines.

   "lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Path3DCollection.set:46", 
   "lib/mpl_toolkits/mplot3d/art3d.py:docstring of matplotlib.artist.Poly3DCollection.set:44" 

@QuLogic
Copy link
Member

QuLogic commented Aug 24, 2024

It's not complaining about Poly3DCollection.__init__, but Poly3DCollection.set, which is one of the weird automatic substitutions of all possible keyword arguments, but I'm not sure which one changed. It's probably easiest to build locally with missing_references_write_json = True and see what lines changed.

Also, I just noticed this looking at other arguments, but axlim_clip should probably get a .. versionadded:: directive in its docs.

@scottshambaugh
Copy link
Contributor Author

@QuLogic I'm not seeing this error on local docs builds. Do you know of another way to track it down?

@scottshambaugh scottshambaugh force-pushed the 3d_dynamic_masking branch 4 times, most recently from 70c8344 to 439841a Compare August 31, 2024 15:44
Implement dynamic clipping to axes box for 3D plots

Make axlim_clip flag keyword only

Updates

test image

test image restore

Implement dynamic clipping to axes box for 3D plots

Make axlim_clip flag keyword only

Updates

test image

test image restore

Implement dynamic clipping to axes box for 3D plots

Make axlim_clip flag keyword only

Updates

test image

test image restore

Code review comments on 3D axlim clipping

Code review comments on 3D axlim clipping
@scottshambaugh
Copy link
Contributor Author

scottshambaugh commented Aug 31, 2024

Ok, fixed the issue with WARNING: py:meth reference target not found! For future reference, I deleted the two lines in ./doc/missing-references.json, pushed and waited for CI to throw the build error, and then re-added the lines with the errored line numbers.

The remaining docs error is an instance of #28744 and is unrelated.

@QuLogic I also added in .. versionadded:: 3.10 everywhere applicable, think this is good to go now.

@QuLogic QuLogic merged commit 9dceafc into matplotlib:main Oct 2, 2024
41 of 43 checks passed
@nbfazel
Copy link

nbfazel commented Oct 5, 2024

Thank you for addressing this issue!

Which version of matplotlib will incorporate the fix? My current version is 3.9.2.

@scottshambaugh
Copy link
Contributor Author

Hi @nbfazel, this will be out in the future 3.10 release.

@nbfazel
Copy link

nbfazel commented Oct 6, 2024

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Issue with setting axis limits on 3D plots
4 participants