Closed
Description
Bug summary
New (appears in matplotlib=3.5
) an AttributeError
is thrown stating 'Arrow3D' object has no attribute 'do_3d_projection'
.
The error appears when running, e.g., the nice example https://stackoverflow.com/a/29188796 by @tacaswell . Below I extracted a MWE from the stackoverflow code.
Code for reproduction
# MWE extracted from https://stackoverflow.com/a/29188796 by @tacaswell
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d
class Arrow3D(FancyArrowPatch):
def __init__(self, xs, ys, zs, *args, **kwargs):
FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs)
self._verts3d = xs, ys, zs
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
FancyArrowPatch.draw(self, renderer)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
arrow_prop_dict = dict(mutation_scale=20, arrowstyle='-|>', color='k', shrinkA=0, shrinkB=0)
a = Arrow3D([0, 10], [0, 0], [0, 0], **arrow_prop_dict)
ax.add_artist(a)
Actual outcome
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~/anaconda3/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj)
339 pass
340 else:
--> 341 return printer(obj)
342 # Finally look for special method names
343 method = get_real_method(obj, self.print_method)
~/anaconda3/lib/python3.8/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
248
249 if 'png' in formats:
--> 250 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
251 if 'retina' in formats or 'png2x' in formats:
252 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
~/anaconda3/lib/python3.8/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
132 FigureCanvasBase(fig)
133
--> 134 fig.canvas.print_figure(bytes_io, **kw)
135 data = bytes_io.getvalue()
136 if fmt == 'svg':
~/anaconda3/lib/python3.8/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2288 )
2289 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2290 self.figure.draw(renderer)
2291
2292 if bbox_inches:
~/anaconda3/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
71 @wraps(draw)
72 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 73 result = draw(artist, renderer, *args, **kwargs)
74 if renderer._rasterizing:
75 renderer.stop_rasterizing()
~/anaconda3/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
2801
2802 self.patch.draw(renderer)
-> 2803 mimage._draw_list_compositing_images(
2804 renderer, self, artists, self.suppressComposite)
2805
~/anaconda3/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
~/anaconda3/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/lib/python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py in draw(self, renderer)
445 for axis in self._get_axis_list()) + 1
446 collection_zorder = patch_zorder = zorder_offset
--> 447 for artist in sorted(collections_and_patches,
448 key=do_3d_projection,
449 reverse=True):
~/anaconda3/lib/python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py in do_3d_projection(artist)
434 "do_3d_projection() was deprecated in Matplotlib "
435 "%(since)s and will be removed %(removal)s.")
--> 436 return artist.do_3d_projection(renderer)
437
438 collections_and_patches = (
AttributeError: 'Arrow3D' object has no attribute 'do_3d_projection'
[@tacaswell edited to add markup]
Expected outcome
Should draw the fancy arrow.
Additional information
This worked before matplotlib 3.5; error appears in different Python versions and different backends.
Operating system
Linux
Matplotlib Version
3.5.0
Matplotlib Backend
module://ipykernel.pylab.backend_inline
Python version
No response
Jupyter version
No response
Installation
conda