Skip to content

[Bug]: mplot3d - axes3d has_data() type checking #28694

@Chad-V

Description

@Chad-V

Bug summary

The Axes3D.has_data() method, to check if added collections have anything within them, isn't overridden at all from the original BaseAxes version. That version tests for Line2D, Collection, AxesImage, and Patch; therefore, the 3D collections are not saved to the Axes3D or other 3D artists, and when coll.remove() is called later, there's an error saying they aren't in any collection.

Code for reproduction

class Plot(wx.Panel):
    def __init__(self, parent, id=-1, dpi=None, **kwargs):
        super().__init__(parent, id=id, **kwargs)

        self.Figure = Figure(dpi=dpi, figsize=(2,2))
        self.Canvas = FigureCanvas(self, -1, self.Figure)
        self.Toolbar = NavigationToolbar(self.Canvas)
        self.Toolbar.Realize()

        sz = wx.BoxSizer(wx.VERTICAL)
        sz.Add(self.Canvas, 1, wx.EXPAND)
        sz.Add(self.Toolbar, 0, wx.LEFT | wx.EXPAND)
        self.SetSizer(sz)

def SetupPlot(plot_holder):
        peak_plot_3d = Plot(plot_holder)

        ax = peak_plot_3d.Figure.add_subplot(projection='3d')
        ax: Axes3D

        ax.set_xlim3d(-5, 5)
        ax.set_ylim3d(-5, 5)
        ax.set_zlim3d(-10, 10)
        
        plot: Line3DCollection
        plot = ax.plot_wireframe(x, y, z)

        plot.remove() # Error triggers here; the return from plot_wireframe is never added to the Axes3D object.

Actual outcome

PDB output when navigating to the has_data() method, right after calling ax.plot_wireframe():
c:\users\chadv\source\demos\python application - wxpython\env\lib\site-packages\matplotlib\axes_base.py(2236)has_data()->False-> return any(isinstance(a, (mcoll.Collection, mimage.AxesImage,

Error output after calling plot.remove()
File "C:\Users\chadv\source\Demos\Python Application - WxPython\src\gui\examples\matplot.py", line 244, in SetupPeak
plot.remove()
File "C:\Users\chadv\source\Demos\Python Application - WxPython\env\Lib\site-packages\matplotlib\artist.py", line 240, in remove
self._remove_method(self)
ValueError: list.remove(x): x not in list

Expected outcome

I expect to be able to remove the Line3DCollection from the Axes3D.

Additional information

Pretty sure the solution here would be to override the method has_data() in Axes3D, and potentially other 3D collections.

Operating system

Windows

Matplotlib Version

3.9.1.post1

Matplotlib Backend

wxagg

Python version

3.12.3

Jupyter version

n/a

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions