Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: array-like linewidth raises an error for scatter3D #23433

Closed
krassowski opened this issue Jul 16, 2022 · 1 comment · Fixed by #23434
Closed

[Bug]: array-like linewidth raises an error for scatter3D #23433

krassowski opened this issue Jul 16, 2022 · 1 comment · Fixed by #23434
Milestone

Comments

@krassowski
Copy link
Contributor

krassowski commented Jul 16, 2022

Bug summary

The documentation says that linewidths can be float or array-like and it defaults to 1.5, but passing an array-like leads to an error

Code for reproduction

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
x = range(1, 10)
ax.scatter(x, x, x, marker='o', s=x, linewidth=x)
plt.show()

Actual outcome

Exception:

mpl_toolkits/mplot3d/axes3d.py in do_3d_projection(artist)
    469                     # avoid passing it to them; call this directly once the
    470                     # deprecation has expired.
--> 471                     return artist.do_3d_projection()
    472 
    473                 _api.warn_deprecated(

matplotlib/_api/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    429                          else deprecation_addendum,
    430                 **kwargs)
--> 431         return func(*inner_args, **inner_kwargs)
    432 
    433     return wrapper

mpl_toolkits/mplot3d/art3d.py in do_3d_projection(self, renderer)
    615 
    616         if len(self._linewidths3d) > 1:
--> 617             self._linewidths = self._linewidths3d[z_markers_idx]
    618 
    619         # Re-order items

TypeError: only integer scalar arrays can be converted to a scalar index

gets raised, from:

if len(self._sizes3d) > 1:
self._sizes = self._sizes3d[z_markers_idx]
if len(self._linewidths3d) > 1:
self._linewidths = self._linewidths3d[z_markers_idx]

This is because the type of self._sizes3d is numpy.ndarray, but type of self._linewidths3d is list.

Expected outcome

Array-like linewidth works for 3d plots as it does for 2d plots.

Additional information

  • ax.scatter(x, x, x, marker='o', s=x) works fine.
  • linewidths is a list regardless of user input type.
  • I don't know where linewidths gets converted to a list, but a quick fix is as simple as wrapping it in np.array call: self._linewidths = np.array(self._linewidths3d)[z_markers_idx] (tested that this fixes the issue).

Operating system

No response

Matplotlib Version

3.5.2 but also happens with older versions (3.3.x)

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

pip

@krassowski
Copy link
Contributor Author

The conversion to list happens in parent class' (PathCollection) set_linewidth:

def set_linewidth(self, lw):
"""
Set the linewidth(s) for the collection. *lw* can be a scalar
or a sequence; if it is a sequence the patches will cycle
through the sequence
Parameters
----------
lw : float or list of floats
"""
if lw is None:
lw = self._get_default_linewidth()
# get the un-scaled/broadcast lw
self._us_lw = np.atleast_1d(np.asarray(lw))
# scale all of the dash patterns.
self._linewidths, self._linestyles = self._bcast_lwls(
self._us_lw, self._us_linestyles)

which gets called via super():

def set_linewidth(self, lw):
super().set_linewidth(lw)
if not self._in_draw:
self._linewidth3d = lw

More specifically, the call to self._bcast_lwls leads to the linewidth getting converted to a list here:

linewidths = list(linewidths) * (l_dashes // gcd)

The safest solution would be to cast to numpy array in do_3d_projection, but it feels like _bcast_lwls should return a numpy array in first place (though such a change could break something elsewhere if there are other parts of the codebase expecting it to be a list). Any preferences?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants