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

Skip to content

Commit fafc0cf

Browse files
committed
Merge pull request #400 from mdboom/marker_scatter_reconcile
Marker/scatter reconciliation
2 parents d1c7fdf + c9e0ebc commit fafc0cf

21 files changed

Lines changed: 2665 additions & 1996 deletions

CHANGELOG

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2011-07-15 The set of markers available in the plot() and scatter()
2+
commands has been unified. In general, this gives more
3+
options to both than were previously available, however,
4+
there is one backward-incompatible change to the markers in
5+
scatter:
6+
7+
"d" used to mean "diamond", it now means "narrow
8+
diamond". "D" can be used for a "diamond".
9+
10+
-MGD
11+
112
2011-07-10 Fixed argument handling error in tripcolor/triplot/tricontour,
213
issue #203. - IMT
314

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from matplotlib import pyplot as plt
2+
import numpy as np
3+
import matplotlib
4+
5+
x = np.arange(0.0, 50.0, 2.0)
6+
y = x ** 1.3 + np.random.rand(*x.shape) * 30.0
7+
s = np.random.rand(*x.shape) * 800 + 500
8+
9+
plt.scatter(x, y, s, c="g", alpha=0.5, marker=r'$\clubsuit$',
10+
label="Luck")
11+
plt.xlabel("Leprechauns")
12+
plt.ylabel("Gold")
13+
plt.legend(loc=2)
14+
plt.show()

lib/matplotlib/axes.py

Lines changed: 11 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import matplotlib.image as mimage
2323
import matplotlib.legend as mlegend
2424
import matplotlib.lines as mlines
25+
import matplotlib.markers as mmarkers
2526
import matplotlib.mlab as mlab
2627
import matplotlib.path as mpath
2728
import matplotlib.patches as mpatches
@@ -5651,48 +5652,7 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
56515652
*marker*:
56525653
can be one of:
56535654
5654-
======= ==============
5655-
Value Description
5656-
======= ==============
5657-
``'s'`` square
5658-
``'o'`` circle
5659-
``'^'`` triangle up
5660-
``'>'`` triangle right
5661-
``'v'`` triangle down
5662-
``'<'`` triangle left
5663-
``'d'`` diamond
5664-
``'p'`` pentagon
5665-
``'h'`` hexagon
5666-
``'8'`` octagon
5667-
``'+'`` plus
5668-
``'x'`` cross
5669-
======= ==============
5670-
5671-
The marker can also be a tuple (*numsides*, *style*,
5672-
*angle*), which will create a custom, regular symbol.
5673-
5674-
*numsides*:
5675-
the number of sides
5676-
5677-
*style*:
5678-
the style of the regular symbol:
5679-
5680-
===== =============================================
5681-
Value Description
5682-
===== =============================================
5683-
0 a regular polygon
5684-
1 a star-like symbol
5685-
2 an asterisk
5686-
3 a circle (*numsides* and *angle* is ignored)
5687-
===== =============================================
5688-
5689-
*angle*:
5690-
the angle of rotation of the symbol
5691-
5692-
Finally, *marker* can be (*verts*, 0): *verts* is a
5693-
sequence of (*x*, *y*) vertices for a custom scatter
5694-
symbol. Alternatively, use the kwarg combination
5695-
*marker* = *None*, *verts* = *verts*.
5655+
%(MarkerTable)s
56965656
56975657
Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in
56985658
which case all masks will be combined and only unmasked points
@@ -5749,21 +5709,6 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
57495709

57505710
if not self._hold: self.cla()
57515711

5752-
syms = { # a dict from symbol to (numsides, angle)
5753-
's' : (4,math.pi/4.0,0), # square
5754-
'o' : (0,0,3), # circle
5755-
'^' : (3,0,0), # triangle up
5756-
'>' : (3,math.pi/2.0,0), # triangle right
5757-
'v' : (3,math.pi,0), # triangle down
5758-
'<' : (3,3*math.pi/2.0,0), # triangle left
5759-
'd' : (4,0,0), # diamond
5760-
'p' : (5,0,0), # pentagon
5761-
'h' : (6,0,0), # hexagon
5762-
'8' : (8,0,0), # octagon
5763-
'+' : (4,0,2), # plus
5764-
'x' : (4,math.pi/4.0,2) # cross
5765-
}
5766-
57675712
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
57685713
x = self.convert_xunits(x)
57695714
y = self.convert_yunits(y)
@@ -5814,87 +5759,21 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
58145759
marker = (verts, 0)
58155760
verts = None
58165761

5817-
if is_string_like(marker):
5818-
# the standard way to define symbols using a string character
5819-
sym = syms.get(marker)
5820-
if sym is None and verts is None:
5821-
raise ValueError('Unknown marker symbol to scatter')
5822-
numsides, rotation, symstyle = syms[marker]
5823-
5824-
elif iterable(marker):
5825-
# accept marker to be:
5826-
# (numsides, style, [angle])
5827-
# or
5828-
# (verts[], style, [angle])
5829-
5830-
if len(marker)<2 or len(marker)>3:
5831-
raise ValueError('Cannot create markersymbol from marker')
5832-
5833-
if cbook.is_numlike(marker[0]):
5834-
# (numsides, style, [angle])
5835-
5836-
if len(marker)==2:
5837-
numsides, rotation = marker[0], 0.
5838-
elif len(marker)==3:
5839-
numsides, rotation = marker[0], marker[2]
5840-
sym = True
5841-
5842-
if marker[1] in (1,2,3):
5843-
symstyle = marker[1]
5844-
5845-
else:
5846-
verts = np.asarray(marker[0])
5847-
5848-
if sym is not None:
5849-
if symstyle==0:
5850-
collection = mcoll.RegularPolyCollection(
5851-
numsides, rotation, scales,
5852-
facecolors = colors,
5853-
edgecolors = edgecolors,
5854-
linewidths = linewidths,
5855-
offsets = zip(x,y),
5856-
transOffset = self.transData,
5857-
)
5858-
elif symstyle==1:
5859-
collection = mcoll.StarPolygonCollection(
5860-
numsides, rotation, scales,
5861-
facecolors = colors,
5862-
edgecolors = edgecolors,
5863-
linewidths = linewidths,
5864-
offsets = zip(x,y),
5865-
transOffset = self.transData,
5866-
)
5867-
elif symstyle==2:
5868-
collection = mcoll.AsteriskPolygonCollection(
5869-
numsides, rotation, scales,
5870-
facecolors = colors,
5871-
edgecolors = 'face',
5872-
linewidths = linewidths,
5873-
offsets = zip(x,y),
5874-
transOffset = self.transData,
5875-
)
5876-
elif symstyle==3:
5877-
collection = mcoll.CircleCollection(
5878-
scales,
5879-
facecolors = colors,
5880-
edgecolors = edgecolors,
5881-
linewidths = linewidths,
5882-
offsets = zip(x,y),
5883-
transOffset = self.transData,
5884-
)
5885-
else:
5886-
rescale = np.sqrt(max(verts[:,0]**2+verts[:,1]**2))
5887-
verts /= rescale
5888-
5889-
collection = mcoll.PolyCollection(
5890-
(verts,), scales,
5762+
marker_obj = mmarkers.MarkerStyle(marker)
5763+
path = marker_obj.get_path().transformed(
5764+
marker_obj.get_transform())
5765+
if not marker_obj.is_filled():
5766+
edgecolors = 'face'
5767+
5768+
collection = mcoll.PathCollection(
5769+
(path,), scales,
58915770
facecolors = colors,
58925771
edgecolors = edgecolors,
58935772
linewidths = linewidths,
58945773
offsets = zip(x,y),
58955774
transOffset = self.transData,
58965775
)
5897-
collection.set_transform(mtransforms.IdentityTransform())
5776+
collection.set_transform(mtransforms.IdentityTransform())
58985777
collection.set_alpha(alpha)
58995778
collection.update(kwargs)
59005779

lib/matplotlib/backends/backend_gtk.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def fn_name(): return sys._getframe(1).f_code.co_name
3232
from matplotlib.widgets import SubplotTool
3333

3434
from matplotlib import lines
35+
from matplotlib import markers
3536
from matplotlib import cbook
3637
from matplotlib import verbose
3738

@@ -1076,7 +1077,7 @@ class DialogLineprops:
10761077
linestyled = dict([ (s,i) for i,s in enumerate(linestyles)])
10771078

10781079

1079-
markers = [m for m in lines.Line2D.markers if cbook.is_string_like(m)]
1080+
markers = [m for m in markers.MarkerStyle.markers if cbook.is_string_like(m)]
10801081

10811082
markerd = dict([(s,i) for i,s in enumerate(markers)])
10821083

lib/matplotlib/backends/qt4_editor/figureoptions.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import matplotlib.backends.qt4_editor.formlayout as formlayout
1212
from matplotlib.backends.qt4_compat import QtGui
13+
from matplotlib import markers
1314

1415
def get_icon(name):
1516
import matplotlib
@@ -25,30 +26,7 @@ def get_icon(name):
2526
'none': 'None',
2627
}
2728

28-
MARKERS = {
29-
'none': 'None',
30-
'o': 'circles',
31-
'^': 'triangle_up',
32-
'v': 'triangle_down',
33-
'<': 'triangle_left',
34-
'>': 'triangle_right',
35-
's': 'square',
36-
'+': 'plus',
37-
'x': 'cross',
38-
'*': 'star',
39-
'D': 'diamond',
40-
'd': 'thin_diamond',
41-
'1': 'tripod_down',
42-
'2': 'tripod_up',
43-
'3': 'tripod_left',
44-
'4': 'tripod_right',
45-
'h': 'hexagon',
46-
'H': 'rotated_hexagon',
47-
'p': 'pentagon',
48-
'|': 'vertical_line',
49-
'_': 'horizontal_line',
50-
'.': 'dots',
51-
}
29+
MARKERS = markers.MarkerStyle.markers
5230

5331
COLORS = {'b': '#0000ff', 'g': '#00ff00', 'r': '#ff0000', 'c': '#ff00ff',
5432
'm': '#ff00ff', 'y': '#ffff00', 'k': '#000000', 'w': '#ffffff'}

lib/matplotlib/collections.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ class PathCollection(Collection):
574574
This is the most basic :class:`Collection` subclass.
575575
"""
576576
@docstring.dedent_interpd
577-
def __init__(self, paths, **kwargs):
577+
def __init__(self, paths, sizes=None, **kwargs):
578578
"""
579579
*paths* is a sequence of :class:`matplotlib.path.Path`
580580
instances.
@@ -584,11 +584,25 @@ def __init__(self, paths, **kwargs):
584584

585585
Collection.__init__(self, **kwargs)
586586
self.set_paths(paths)
587-
587+
self._sizes = sizes
588588

589589
def set_paths(self, paths):
590590
self._paths = paths
591-
591+
592+
def get_paths(self):
593+
return self._paths
594+
595+
def get_sizes(self):
596+
return self._sizes
597+
598+
@allow_rasterization
599+
def draw(self, renderer):
600+
if self._sizes is not None:
601+
self._transforms = [
602+
transforms.Affine2D().scale(
603+
(np.sqrt(x) * self.figure.dpi / 72.0))
604+
for x in self._sizes]
605+
return Collection.draw(self, renderer)
592606

593607
class PolyCollection(Collection):
594608
@docstring.dedent_interpd

lib/matplotlib/legend.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from matplotlib.lines import Line2D
2424
from matplotlib.patches import Patch, Rectangle, Shadow, FancyBboxPatch
2525
from matplotlib.collections import LineCollection, RegularPolyCollection, \
26-
CircleCollection
26+
CircleCollection, PathCollection
2727
from matplotlib.transforms import Bbox, BboxBase, TransformedBbox, BboxTransformTo, BboxTransformFrom
2828

2929
from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea, DraggableOffsetBox
@@ -481,6 +481,7 @@ def _approx_text_height(self, renderer=None):
481481
CircleCollection:legend_handler.HandlerCircleCollection(),
482482
BarContainer:legend_handler.HandlerPatch(update_func=legend_handler.update_from_first_child),
483483
tuple:legend_handler.HandlerTuple(),
484+
PathCollection:legend_handler.HandlerPathCollection()
484485
}
485486

486487
# (get|set|update)_default_handler_maps are public interfaces to

lib/matplotlib/legend_handler.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,19 @@ def create_artists(self, legend, orig_handle,
362362

363363
return [p]
364364

365+
class HandlerPathCollection(HandlerRegularPolyCollection):
366+
"""
367+
Handler for PathCollections, which are used by scatter
368+
"""
369+
def create_collection(self, orig_handle, sizes, offsets, transOffset):
370+
p = type(orig_handle)([orig_handle.get_paths()[0]],
371+
sizes=sizes,
372+
offsets=offsets,
373+
transOffset=transOffset,
374+
)
375+
return p
365376

377+
366378
class HandlerCircleCollection(HandlerRegularPolyCollection):
367379
"""
368380
Handler for CircleCollections

0 commit comments

Comments
 (0)