Fix restoring 'auto' aspect in 3D axes after switching from 'equal'#31304
Fix restoring 'auto' aspect in 3D axes after switching from 'equal'#31304jayaprajapatii wants to merge 1 commit into
Conversation
|
I'm not too familiar with 3D plotting, but the test explicitly set the box aspect. If a user did similarly, shouldn't we respect it? matplotlib/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Lines 88 to 89 in 32805b1 |
|
Thanks @rcomer Would it make more sense to only reset the box aspect when it was implicitly modified by the equal-aspect logic, rather than when it was explicitly set by the user? |
|
I think that overriding a previously set aspect with "auto" is the correct behavior. But we should have different behavior with setting "auto" on the "datalim" - the box shouldn't be modified in that case. |
scottshambaugh
left a comment
There was a problem hiding this comment.
The test image was changed in separate commits, so that needs to be git squashed or rebased to fix the "PR Cleanliness" failure.
Also, this new behavior needs to be tested.
e8db81d to
a4d63fa
Compare
scottshambaugh
left a comment
There was a problem hiding this comment.
Ok, I think this is looking good for the adjustable='box' case. What's the current behavior for 'datalim'? That should be fixed at the same time as well.
|
Hello @scottshambaugh Updated I verified that in the |
|
What is the current behavior for 'datalim'? Please share screenshots, and try to set up a case where this is exercised. I don't think the test added for the datalim case is meaningfully doing anything right now. |
|
The auto with datalim should give the same limits in both cases here (which should both match the default autoscaling): import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1, 1, subplot_kw={'projection': '3d'})
ax.plot([0, 1], [0, 1], [0, 1])
print('default:', np.array(ax.get_w_lims()))
ax.set_aspect('auto', 'datalim')
print('auto:', np.array(ax.get_w_lims()))
ax.set_aspect('equal', 'datalim')
print('equal:', np.array(ax.get_w_lims()))
ax.set_aspect('auto', 'datalim')
print('auto:', np.array(ax.get_w_lims())) |
|
Hi @jayaprajapatii are you still interested in working on this? I think you may need to rebase to main to get the tests working again |
|
Thankyou @scottshambaugh |
3d6cd1f to
2c505d5
Compare
|
Hi @jayaprajapatii are you still interested in working on this? The baseline image test failure is real. |
|
Ok almost there - you'll need to squash /rebase your commits so the |
1b03c4c to
cc7babe
Compare
|
I don't see any visual changes in the |
cc7babe to
672356e
Compare
scottshambaugh
left a comment
There was a problem hiding this comment.
This looks good for me, thanks for putting it together!
| self._aspect == "auto" | ||
| and aspect in ('equal', 'equalxy', 'equalxz', 'equalyz') | ||
| ): | ||
| self._auto_aspect_restore_limits = self.get_w_lims() |
There was a problem hiding this comment.
Why is this an attribute? It only appears to be used in this method.
There was a problem hiding this comment.
Hii @QuLogic ,
I think the limits need to persist across separate set_aspect calls when switching back from "equal" to "auto", which is why I stored them on the instance.
There was a problem hiding this comment.
I understood that part between switching modes. What I don't understand is how it manages to work if you change w_lims (i.e., xlim, ylim, or zlim) between switching.
~That is, this does work now:~
ax2.set_aspect('auto', adjustable='datalim')
ax2.set_xlim([-50, 50])
fig2.savefig('3d-plot1.png') # Correct
ax2.set_aspect('equal', adjustable='datalim')
ax2.set_xlim([-50, 50])
ax2.set_aspect('auto', adjustable='datalim')
fig2.savefig('3d-plot2.png') # Previously wrong (inconsistent with 3d-plot1.png) but fixed in this PR.but I'm missing where the persisted limits get refreshed.
There was a problem hiding this comment.
No wait, I'm dumb; my example doesn't work. It's just that I set the xlim on the Axes before the first save, so of course it carried through to the second one. When doing it individually, this PR is still incorrect:
fig2 = plt.figure()
ax2 = fig2.add_subplot(projection='3d')
X, Y, Z = axes3d.get_test_data()
ax2.contourf(X, Y, Z, cmap="coolwarm")
ax2.set_aspect('auto', adjustable='datalim')
ax2.set_xlim([-50, 50])
fig2.savefig('3d-plot1.png') # Correct
fig3 = plt.figure()
ax3 = fig3.add_subplot(projection='3d')
X, Y, Z = axes3d.get_test_data()
ax3.contourf(X, Y, Z, cmap="coolwarm")
ax3.set_aspect('equal', adjustable='datalim')
ax3.set_xlim([-50, 50])
ax3.set_aspect('auto', adjustable='datalim')
fig3.savefig('3d-plot2.png') # Wrong (inconsistent with 3d-plot1.png)|
Hello @QuLogic Just a gentle ping, please have a look at this PR. |
d889829 to
1d08ff6
Compare
1d08ff6 to
7e7d7f8
Compare


Closes #31276
Switching the aspect of a 3D axis from
"auto"to"equal"and then back to"auto"did not restore the original plot correctly. The logic for handling"auto"continued executing the equal-aspect adjustments, which modified the axis limits and box aspect.This change ensures that when
aspect == "auto", the box aspect is reset and the function exits early, preventing further equal-aspect logic from running.The baseline image for
test_aspectshas been updated to reflect the corrected rendering.