| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Do you know what version of Matplotlib this last worked with? Thanks!
It starts to fail with v3.5.0. v3.4.3 is still fine.
I think this is another bit of fallout from merging the internal representation of axes children from any lists to 1 list. Previously, the Arrow3D here would be in a list that was did not participate in the z-order sorting, and hence that it was missing one of the methods from the 3D api was missed. However, now that we have them merged, we reconstruct the old lists (which were nominally sorted by type) by picking out all of the children of the right type.
The fix here is to correct Arrow3D to have the missing method:
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):
super().__init__((0,0), (0,0), *args, **kwargs)
self._verts3d = xs, ys, zs
def do_3d_projection(self, renderer=None):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
return np.min(zs)
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)
plt.show()This works fine, thanks @tacaswell !
def do_3d_projection(self, render=None):
That should be renderer, not render, though I don't believe anything calls it with the name explicitly.
Exact Code .. here
%pylab inline
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d
from matplotlib.patches import FancyArrowPatch
%matplotlib inline
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 do_3d_projection(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
FancyArrowPatch.draw(self, renderer)
return np.min(zs)
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111, projection='3d')
ax.plot(df['feature1'], df['feature2'], df['feature3'], 'o', markersize=8, color='blue', alpha=0.2)
ax.plot([df['feature1'].mean()], [df['feature2'].mean()], [df['feature3'].mean()], 'o', markersize=10, color='red', alpha=0.5)
for v in eigen_vectors.T:
a = Arrow3D([df['feature1'].mean(), v[0]], [df['feature2'].mean(), v[1]], [df['feature3'].mean(), v[2]], mutation_scale=20, lw=3, arrowstyle="-|>", color="r")
ax.add_artist(a)
ax.set_xlabel('x_values')
ax.set_ylabel('y_values')
ax.set_zlabel('z_values')
plt.title('Eigenvectors')
plt.show()
@Siddhartha082 I do not understand what you are trying to say.
Thanks you @tacaswell !
I think this is another bit of fallout from merging the internal representation of axes children from any lists to 1 list. Previously, the Arrow3D here would be in a list that was did not participate in the z-order sorting, and hence that it was missing one of the methods from the 3D api was missed. However, now that we have them merged, we reconstruct the old lists (which were nominally sorted by type) by picking out all of the children of the right type.
The fix here is to correct Arrow3D to have the missing method:
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): super().__init__((0,0), (0,0), *args, **kwargs) self._verts3d = xs, ys, zs def do_3d_projection(self, renderer=None): xs3d, ys3d, zs3d = self._verts3d xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M) self.set_positions((xs[0],ys[0]),(xs[1],ys[1])) return np.min(zs) 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) plt.show()
NB,NB,NB
Can this class just be added to the library?
| Back | FazBrowse Home | New Git URL |
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
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