The figure above was produced by this code
%matplotlib
import numpy as np
import matplotlib.pyplot as plt
x = y = np.array([1, 2])
fig = plt.figure(figsize=(5, 3))
ax1 = fig.add_subplot(111, projection='3d')
ax1.bar3d(x, y, [0,0], 0.5, 0.5, [1,1], shade=True, label='a')
ax1.bar3d(x, y, [1,1], 0.5, 0.5, [1,1], shade=True, label='b')
ax1.legend()
that asked also for a legend. As you can see, no legend but I've got this Traceback
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[1], line 12
10 ax1.bar3d(x, y, [0,0], 0.5, 0.5, [1,1], shade=True, label='a')
11 ax1.bar3d(x, y, [1,1], 0.5, 0.5, [1,1], shade=True, label='b')
---> 12 plt.legend()
File /usr/lib64/python3.11/site-packages/matplotlib/pyplot.py:2646, in legend(*args, **kwargs)
2644 @_copy_docstring_and_deprecators(Axes.legend)
2645 def legend(*args, **kwargs):
-> 2646 return gca().legend(*args, **kwargs)
File /usr/lib64/python3.11/site-packages/matplotlib/axes/_axes.py:313, in Axes.legend(self, *args, **kwargs)
311 if len(extra_args):
312 raise TypeError('legend only accepts two non-keyword arguments')
--> 313 self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
314 self.legend_._remove_method = self._remove_legend
315 return self.legend_
File /usr/lib64/python3.11/site-packages/matplotlib/_api/deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
448 if len(args) > name_idx:
449 warn_deprecated(
450 since, message="Passing the %(name)s %(obj_type)s "
451 "positionally is deprecated since Matplotlib %(since)s; the "
452 "parameter will become keyword-only %(removal)s.",
453 name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)
File /usr/lib64/python3.11/site-packages/matplotlib/legend.py:517, in Legend.__init__(self, parent, handles, labels, loc, numpoints, markerscale, markerfirst, scatterpoints, scatteryoffsets, prop, fontsize, labelcolor, borderpad, labelspacing, handlelength, handleheight, handletextpad, borderaxespad, columnspacing, ncols, mode, fancybox, shadow, title, title_fontsize, framealpha, edgecolor, facecolor, bbox_to_anchor, bbox_transform, frameon, handler_map, title_fontproperties, alignment, ncol)
514 self._alignment = alignment
516 # init with null renderer
--> 517 self._init_legend_box(handles, labels, markerfirst)
519 tmp = self._loc_used_default
520 self._set_loc(loc)
File /usr/lib64/python3.11/site-packages/matplotlib/legend.py:782, in Legend._init_legend_box(self, handles, labels, markerfirst)
779 text_list.append(textbox._text)
780 # Create the artist for the legend which represents the
781 # original artist/handle.
--> 782 handle_list.append(handler.legend_artist(self, orig_handle,
783 fontsize, handlebox))
784 handles_and_labels.append((handlebox, textbox))
786 columnbox = []
File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:119, in HandlerBase.legend_artist(self, legend, orig_handle, fontsize, handlebox)
95 """
96 Return the artist that this HandlerBase generates for the given
97 original artist/handle.
(...)
112
113 """
114 xdescent, ydescent, width, height = self.adjust_drawing_area(
115 legend, orig_handle,
116 handlebox.xdescent, handlebox.ydescent,
117 handlebox.width, handlebox.height,
118 fontsize)
--> 119 artists = self.create_artists(legend, orig_handle,
120 xdescent, ydescent, width, height,
121 fontsize, handlebox.get_transform())
123 if isinstance(artists, _Line2DHandleList):
124 artists = [artists[0]]
File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:806, in HandlerPolyCollection.create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans)
802 def create_artists(self, legend, orig_handle,
803 xdescent, ydescent, width, height, fontsize, trans):
804 p = Rectangle(xy=(-xdescent, -ydescent),
805 width=width, height=height)
--> 806 self.update_prop(p, orig_handle, legend)
807 p.set_transform(trans)
808 return [p]
File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:78, in HandlerBase.update_prop(self, legend_handle, orig_handle, legend)
76 def update_prop(self, legend_handle, orig_handle, legend):
---> 78 self._update_prop(legend_handle, orig_handle)
80 legend._set_artist_props(legend_handle)
81 legend_handle.set_clip_box(None)
File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:787, in HandlerPolyCollection._update_prop(self, legend_handle, orig_handle)
783 return None
785 # orig_handle is a PolyCollection and legend_handle is a Patch.
786 # Directly set Patch color attributes (must be RGBA tuples).
--> 787 legend_handle._facecolor = first_color(orig_handle.get_facecolor())
788 legend_handle._edgecolor = first_color(orig_handle.get_edgecolor())
789 legend_handle._original_facecolor = orig_handle._original_facecolor
File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:775, in HandlerPolyCollection._update_prop.<locals>.first_color(colors)
774 def first_color(colors):
--> 775 if colors.size == 0:
776 return (0, 0, 0, 0)
777 return tuple(colors[0])
AttributeError: 'tuple' object has no attribute 'size'
Can you help me at understanding what happened?