From 1ce0e8e8ed019269fd46fa1ebf6531c7f0964cce Mon Sep 17 00:00:00 2001 From: Rowan Stein Date: Wed, 24 Dec 2025 19:59:30 +0000 Subject: [PATCH] =?UTF-8?q?mplot3d:=20honor=20Axes.visible=20in=20Axes3D.d?= =?UTF-8?q?raw=20by=20early=20return;=20add=20Agg-based=20visibility=20tes?= =?UTF-8?q?t\n\nFixes=20#29.\n\n-=20Add=20early=20return=20in=20Axes3D.dra?= =?UTF-8?q?w=20when=20Axes=20is=20not=20visible,=20mirroring=202D=20Axes.\?= =?UTF-8?q?n-=20Add=20unit=20test=20ensuring=20left=203D=20axes=20renders?= =?UTF-8?q?=20nothing=20when=20set=5Fvisible(False).\n\nTask=20264=20?= =?UTF-8?q?=E2=80=94=20matplotlib=5F=5Fmatplotlib-23314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/mpl_toolkits/mplot3d/axes3d.py | 4 +++ .../tests/test_mplot3d_visibility.py | 33 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 lib/mpl_toolkits/tests/test_mplot3d_visibility.py diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 9db44b7994bb..c77d2a4a7868 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -387,6 +387,10 @@ def apply_aspect(self, position=None): @martist.allow_rasterization def draw(self, renderer): + if renderer is None: + raise RuntimeError("No renderer defined") + if not self.get_visible(): + return self._unstale_viewLim() # draw the background patch diff --git a/lib/mpl_toolkits/tests/test_mplot3d_visibility.py b/lib/mpl_toolkits/tests/test_mplot3d_visibility.py new file mode 100644 index 000000000000..25b5dd305aba --- /dev/null +++ b/lib/mpl_toolkits/tests/test_mplot3d_visibility.py @@ -0,0 +1,33 @@ +import numpy as np + +from matplotlib.figure import Figure +from matplotlib.backends.backend_agg import FigureCanvasAgg + + +def test_axes3d_respects_set_visible_false(): + fig = Figure(figsize=(4, 2), dpi=100) + canvas = FigureCanvasAgg(fig) + + ax1 = fig.add_subplot(1, 2, 1, projection='3d') + ax2 = fig.add_subplot(1, 2, 2, projection='3d') + + ax1.scatter([1], [1], [1]) + ax2.scatter([1], [1], [1], c='r') + + # Hide left axes entirely. + ax1.set_visible(False) + + # Draw and examine pixels. + canvas.draw() + im = np.asarray(canvas.buffer_rgba()) + + # Use a margin to avoid antialiasing artifacts at figure edges. + h, w, _ = im.shape + margin = 5 + left_half = im[margin:-margin, margin:w // 2 - margin, :3] + + # Background is typically uniform; sample a corner pixel. + bg = im[margin, margin, :3] + + # Assert that the left half contains only background pixels. + assert np.all(left_half == bg)