Skip to content

Scatter: make "c" and "s" argument handling more consistent. #13959

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

Merged
merged 5 commits into from
May 1, 2019

Conversation

efiring
Copy link
Member

@efiring efiring commented Apr 14, 2019

Closes #12735.

PR Summary

This is a small modification to #11663. It bases all checks on the sizes rather than the shapes of x, y, and c, consistent with the practice of flattening x and y at an early stage. This simplifies the code and reduces surprises such as those described in #10365 and #12735.

I also added a check that s be a scalar, or that its size match that of x and y. I think this at least partially addresses #12021, and makes the behavior consistent with the docs.

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@efiring efiring changed the title Scatter: make "c" argument handling more consistent. Scatter: make "c" and "s" argument handling more consistent. Apr 15, 2019
c = np.ma.ravel(c_array)
n_elem = c_array.size
if n_elem == xsize:
c = c_array.ravel()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we need this cast to masked here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The method will work regardless, since c_array is some kind of array, and I don't think we are later depending on c being a masked array.

if c_array.shape in [xshape, yshape]:
c = np.ma.ravel(c_array)
n_elem = c_array.size
if n_elem == xsize:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we define n_elem here? its a confusing name now that its a size, and I don't see it adding anything.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't change this--n_elem is being used the same way it was before this PR. Throughout, n_elem is the number of colors, regardless of whether they are coming from a mapping or from an rgba array. It is used only in reporting an error, if one occurs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted the code from scatter to make it more manageable. It's may not always be the best code style, but I didn't change too much to keep the extraction easier to review.

This should now be named csize in resemblence to xsize, ysize.

@@ -4263,18 +4260,17 @@ def _parse_scatter_color_args(c, edgecolors, kwargs, xshape, yshape,
try: # Then is 'c' acceptable as PathCollection facecolors?
colors = mcolors.to_rgba_array(c)
n_elem = colors.shape[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we define n_elem here, and don't use in the next line...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is the way it was, and as far as I can see, it still works as intended, providing information for an error message.

@timhoffm
Copy link
Member

Not sure if this is the right way to go. This makes c and s more compatible with the auto-flatting of x, y.
However, it's at least debatable if auto-flatting is desirable #12735 (comment).

@efiring
Copy link
Member Author

efiring commented Apr 17, 2019

If you want to remove auto-flattening, that's a big change for the users, and a different PR. What would it gain in the code? As far as I can see, it would have very little effect on the total LOC, including the docstring. The problem with c is not the flattening, it is all the different ways it can be specified and can interact with marker color kwargs.

if c_array.shape in [xshape, yshape]:
c = np.ma.ravel(c_array)
n_elem = c_array.size
if n_elem == xsize:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted the code from scatter to make it more manageable. It's may not always be the best code style, but I didn't change too much to keep the extraction easier to review.

This should now be named csize in resemblence to xsize, ysize.

# NB: remember that a single color is also acceptable.
# Besides *colors* will be an empty array if c == 'none'.
valid_shape = False
raise ValueError
except ValueError:
except (ValueError, TypeError):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does the typeerror come from?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In [9]: mcolors.to_rgba_array(None)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-1ff544d60239> in <module>
----> 1 mcolors.to_rgba_array(None)

~/work/programs/py/mpl/matplotlib/lib/matplotlib/colors.py in to_rgba_array(c, alpha)
    282         pass
    283     # Convert one at a time.
--> 284     result = np.empty((len(c), 4), float)
    285     for i, cc in enumerate(c):
    286         result[i] = to_rgba(cc, alpha)

TypeError: object of type 'NoneType' has no len()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to be a pain... but can c really be None at that point? If so, why didn't the previous version need to handle that, or what example (what scatter() call) would cause an uncaught exception in the previous version?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a reasonable question. I added the TypeError because a test was otherwise failing, if I remember correctly. (I can't imagine any other reason I would have put it in.) I think it was because of a None. I will have to take out the TypeError and re-run the tests to find out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying it now without catching the TypeError, tests pass on my machine, so maybe it was needed only at an intermediate stage while I was working on the PR. I've reverted that part of the change. Let's see if the tests still pass here, apart from the unrelated docs problem.

@efiring
Copy link
Member Author

efiring commented Apr 30, 2019

There seems to be a new but unrelated failure in the docs build (involving the hline docstring) after my last commit.

"'y' with size {ys}."
.format(nc=n_elem, xs=xsize, ys=ysize)
"acceptable for use with 'x' and 'y' with size {xs}."
.format(nc=csize, xs=xsize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just make this a f-string, or at least use the same names in the braces and outside (yes, I know, the problem was already there before)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@timhoffm
Copy link
Member

timhoffm commented May 1, 2019

As a heads up: #14113

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 this pull request may close these issues.

Inconsistent shape handling of parameter c compared to x/y in scatter()
5 participants