Thanks to visit codestin.com
Credit goes to github.com

Skip to content

scatter: fix marker kwarg bug. Closes #4073, #3895. #4079

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 2 commits into from
Feb 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 68 additions & 36 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3509,9 +3509,10 @@ def dopatch(xs, ys, **kwargs):
medians=medians, fliers=fliers, means=means)

@docstring.dedent_interpd
def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
def scatter(self, x, y, s=20, c=None, marker='o', cmap=None, norm=None,
vmin=None, vmax=None, alpha=None, linewidths=None,
verts=None, **kwargs):
verts=None, edgecolors=None,
**kwargs):
"""
Make a scatter plot of x vs y, where x and y are sequence like objects
of the same lengths.
Expand All @@ -3531,11 +3532,14 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
(see below). Note that `c` should not be a single numeric RGB or
RGBA sequence because that is indistinguishable from an array of
values to be colormapped. `c` can be a 2-D array in which the
rows are RGB or RGBA, however.
rows are RGB or RGBA, however, including the case of a single
row to specify the same color for all points.

marker : `~matplotlib.markers.MarkerStyle`, optional, default: 'o'
See `~matplotlib.markers` for more information on the different
styles of markers scatter supports.
styles of markers scatter supports. `marker` can be either
an instance of the class or the text shorthand for a particular
marker.

cmap : `~matplotlib.colors.Colormap`, optional, default: None
A `~matplotlib.colors.Colormap` instance or registered name.
Expand All @@ -3557,10 +3561,14 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
The alpha blending value, between 0 (transparent) and 1 (opaque)

linewidths : scalar or array_like, optional, default: None
If None, defaults to (lines.linewidth,). Note that this is a
tuple, and if you set the linewidths argument you must set it as a
sequence of floats, as required by
`~matplotlib.collections.RegularPolyCollection`.
If None, defaults to (lines.linewidth,).

edgecolors : color or sequence of color, optional, default: None
If None, defaults to (patch.edgecolor).
If 'face', the edge color will always be the same as
the face color. If it is 'none', the patch boundary will not
be drawn. For non-filled markers, the `edgecolors` kwarg
is ignored; color is determined by `c`.

Returns
-------
Expand All @@ -3585,6 +3593,32 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
if not self._hold:
self.cla()

# Process **kwargs to handle aliases, conflicts with explicit kwargs:

facecolors = None
ec = kwargs.pop('edgecolor', None)
if ec is not None:
edgecolors = ec
fc = kwargs.pop('facecolor', None)
if fc is not None:
facecolors = fc
fc = kwargs.pop('facecolors', None)
if fc is not None:
facecolors = fc
# 'color' should be deprecated in scatter, or clearly defined;
# since it isn't, I am giving it low priority.
co = kwargs.pop('color', None)
if co is not None:
if edgecolors is None:
edgecolors = co
if facecolors is None:
facecolors = co
Copy link
Member

Choose a reason for hiding this comment

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

Coming in late to the discussion but I have just spent a few minutes trying to determine what I did wrong on my scatter graphs...

I thought c stood as an acronym for color as fc stands for facecolor etcetera... however this does not apply here, specifying color='green' instead of c='green' means you set the edge-colour to green instead of the face-colour...

Should I open an issue/PR about this? Or can people live with this inconsistency?

Copy link
Member

Choose a reason for hiding this comment

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

As far as I understand it, 'c' should be an alias for 'color'. Furthermore,
'color' should specify both edge and face colors, unless explicitly
overriden by 'facecolor' and such.

On Wed, Apr 29, 2015 at 12:45 PM, OceanWolf [email protected]
wrote:

In lib/matplotlib/axes/_axes.py
#4079 (comment):

  •    if ec is not None:
    
  •        edgecolors = ec
    
  •    fc = kwargs.pop('facecolor', None)
    
  •    if fc is not None:
    
  •        facecolors = fc
    
  •    fc = kwargs.pop('facecolors', None)
    
  •    if fc is not None:
    
  •        facecolors = fc
    
  •    # 'color' should be deprecated in scatter, or clearly defined;
    
  •    # since it isn't, I am giving it low priority.
    
  •    co = kwargs.pop('color', None)
    
  •    if co is not None:
    
  •        if edgecolors is None:
    
  •            edgecolors = co
    
  •        if facecolors is None:
    
  •            facecolors = co
    

Coming in late to the discussion but I have just spent a few minutes
trying to determine what I did wrong on my scatter graphs...

I thought c stood as an acronym for color as fc stands for facecolor
etcetera... however this does not apply here, specifying color='green'
instead of c='green' means you set the edge-colour to green instead of
the face-colour...

Should I open an issue/PR about this? Or can people live with this
inconsistency?


Reply to this email directly or view it on GitHub
https://github.com/matplotlib/matplotlib/pull/4079/files#r29355046.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a confusing mess for historical reasons. It looks like there might be a need for "facecolors=None" in the arg list, along with "edgecolors=None". I suspect I had a reason for not including this in the PR, but I don't remember; maybe it is worth a try.

if c is None:
if facecolors is not None:
c = facecolors
else:
c = 'b' # the original default

self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
x = self.convert_xunits(x)
y = self.convert_yunits(y)
Expand All @@ -3598,43 +3632,41 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,

s = np.ma.ravel(s) # This doesn't have to match x, y in size.

c_is_stringy = is_string_like(c) or is_sequence_of_strings(c)
if not c_is_stringy:
c = np.asanyarray(c)
if c.size == x.size:
c = np.ma.ravel(c)
# After this block, c_array will be None unless
# c is an array for mapping. The potential ambiguity
# with a sequence of 3 or 4 numbers is resolved in
# favor mapping, not rgb or rgba.
try:
c_array = np.asanyarray(c, dtype=float)
if c_array.shape == x.shape:
c = np.ma.ravel(c_array)
else:
# Wrong shape; it must not be intended for mapping.
c_array = None
except ValueError:
# Failed to make a floating-point array; c must be color specs.
c_array = None

if c_array is None:
colors = c # must be acceptable as PathCollection facecolors
else:
colors = None # use cmap, norm after collection is created

# c will be unchanged unless it is the same length as x:
x, y, s, c = cbook.delete_masked_points(x, y, s, c)

scales = s # Renamed for readability below.

if c_is_stringy:
colors = mcolors.colorConverter.to_rgba_array(c, alpha)
else:
# The inherent ambiguity is resolved in favor of color
# mapping, not interpretation as rgb or rgba:
if c.size == x.size:
colors = None # use cmap, norm after collection is created
else:
colors = mcolors.colorConverter.to_rgba_array(c, alpha)

faceted = kwargs.pop('faceted', None)
edgecolors = kwargs.get('edgecolors', None)
if faceted is not None:
cbook.warn_deprecated(
'1.2', name='faceted', alternative='edgecolor',
obj_type='option')
if faceted:
edgecolors = None
else:
edgecolors = 'none'

# to be API compatible
if marker is None and not (verts is None):
marker = (verts, 0)
verts = None

marker_obj = mmarkers.MarkerStyle(marker)
if isinstance(marker, mmarkers.MarkerStyle):
marker_obj = marker
else:
marker_obj = mmarkers.MarkerStyle(marker)

path = marker_obj.get_path().transformed(
marker_obj.get_transform())
if not marker_obj.is_filled():
Expand All @@ -3649,9 +3681,9 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
linewidths=linewidths,
offsets=offsets,
transOffset=kwargs.pop('transform', self.transData),
alpha=alpha
)
collection.set_transform(mtransforms.IdentityTransform())
collection.set_alpha(alpha)
collection.update(kwargs)

if colors is None:
Expand Down
12 changes: 6 additions & 6 deletions lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,13 +559,13 @@ def set_color(self, c):
def set_facecolor(self, c):
"""
Set the facecolor(s) of the collection. *c* can be a
matplotlib color arg (all patches have same color), or a
sequence of rgba tuples; if it is a sequence the patches will
matplotlib color spec (all patches have same color), or a
sequence of specs; if it is a sequence the patches will
cycle through the sequence.

If *c* is 'none', the patch will not be filled.

ACCEPTS: matplotlib color arg or sequence of rgba tuples
ACCEPTS: matplotlib color spec or sequence of specs
"""
self._is_filled = True
try:
Expand Down Expand Up @@ -596,15 +596,15 @@ def get_edgecolor(self):
def set_edgecolor(self, c):
"""
Set the edgecolor(s) of the collection. *c* can be a
matplotlib color arg (all patches have same color), or a
sequence of rgba tuples; if it is a sequence the patches will
matplotlib color spec (all patches have same color), or a
sequence of specs; if it is a sequence the patches will
cycle through the sequence.

If *c* is 'face', the edge color will always be the same as
the face color. If it is 'none', the patch boundary will not
be drawn.

ACCEPTS: matplotlib color arg or sequence of rgba tuples
ACCEPTS: matplotlib color spec or sequence of specs
"""
self._is_stroked = True
try:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 19 additions & 1 deletion lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import matplotlib
from matplotlib.testing.decorators import image_comparison, cleanup
import matplotlib.pyplot as plt
import matplotlib.markers as mmarkers
from numpy.testing import assert_array_equal
import warnings

Expand Down Expand Up @@ -1091,7 +1092,24 @@ def test_hist2d_transpose():
@image_comparison(baseline_images=['scatter'])
def test_scatter_plot():
ax = plt.axes()
ax.scatter([3, 4, 2, 6], [2, 5, 2, 3], c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29])
ax.scatter([3, 4, 2, 6], [2, 5, 2, 3],
c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29])


@image_comparison(baseline_images=['scatter_marker'], remove_text=True,
extensions=['png'])
def test_scatter_marker():
fig, (ax0, ax1) = plt.subplots(ncols=2)
ax0.scatter([3, 4, 2, 6], [2, 5, 2, 3],
c=[(1, 0, 0), 'y', 'b', 'lime'],
s=[60, 50, 40, 30],
edgecolors=['k', 'r', 'g', 'b'],
marker='s')
ax1.scatter([3, 4, 2, 6], [2, 5, 2, 3],
c=[(1, 0, 0), 'y', 'b', 'lime'],
s=[60, 50, 40, 30],
edgecolors=['k', 'r', 'g', 'b'],
marker=mmarkers.MarkerStyle('o', fillstyle='top'))


@cleanup
Expand Down