Skip to content

Commit

Permalink
scatter: fix marker kwarg bug. Closes #4073, #3895.
Browse files Browse the repository at this point in the history
I also tried to clean up some of the scatter code and documentation,
together with related documentation in collections.  I added a test.
  • Loading branch information
efiring committed Feb 9, 2015
1 parent ee4f072 commit 18cc8bf
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 42 deletions.
76 changes: 41 additions & 35 deletions lib/matplotlib/axes/_axes.py
Expand Up @@ -3511,7 +3511,8 @@ def dopatch(xs, ys, **kwargs):
@docstring.dedent_interpd
def scatter(self, x, y, s=20, c='b', 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 Down Expand Up @@ -3598,43 +3606,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 +3655,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
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
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
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

0 comments on commit 18cc8bf

Please sign in to comment.