Skip to content

Commit 3c3e8ba

Browse files
authored
Merge pull request #9523 from simonpf/hacktoberfest
Add capstyle and joinstyle attributes to Collection class (Issue #8277)
2 parents e53ee2a + 36b9c46 commit 3c3e8ba

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

doc/users/whats_new.rst

+7
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,13 @@ volumetric model.
246246
Improvements
247247
++++++++++++
248248

249+
Add ``capstyle`` and ``joinstyle`` attributes to `Collection`
250+
-------------------------------------------------------------
251+
252+
The `Collection` class now has customizable ``capstyle`` and ``joinstyle``
253+
attributes. This allows the user for example to set the ``capstyle`` of
254+
errorbars.
255+
249256
CheckButtons widget ``get_status`` function
250257
-------------------------------------------
251258

lib/matplotlib/collections.py

+59
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,16 @@ class Collection(artist.Artist, cm.ScalarMappable):
5252
5353
prop[i % len(props)]
5454
55+
Exceptions are *capstyle* and *joinstyle* properties, these can
56+
only be set globally for the whole collection.
57+
5558
Keyword arguments and default values:
5659
5760
* *edgecolors*: None
5861
* *facecolors*: None
5962
* *linewidths*: None
63+
* *capstyle*: None
64+
* *joinstyle*: None
6065
* *antialiaseds*: None
6166
* *offsets*: None
6267
* *transOffset*: transforms.IdentityTransform()
@@ -104,6 +109,8 @@ def __init__(self,
104109
facecolors=None,
105110
linewidths=None,
106111
linestyles='solid',
112+
capstyle=None,
113+
joinstyle=None,
107114
antialiaseds=None,
108115
offsets=None,
109116
transOffset=None,
@@ -145,6 +152,16 @@ def __init__(self,
145152
self.set_offset_position(offset_position)
146153
self.set_zorder(zorder)
147154

155+
if capstyle:
156+
self.set_capstyle(capstyle)
157+
else:
158+
self._capstyle = None
159+
160+
if joinstyle:
161+
self.set_joinstyle(joinstyle)
162+
else:
163+
self._joinstyle = None
164+
148165
self._offsets = np.zeros((1, 2))
149166
self._uniform_offsets = None
150167
if offsets is not None:
@@ -304,6 +321,12 @@ def draw(self, renderer):
304321
extents.height < height):
305322
do_single_path_optimization = True
306323

324+
if self._joinstyle:
325+
gc.set_joinstyle(self._joinstyle)
326+
327+
if self._capstyle:
328+
gc.set_capstyle(self._capstyle)
329+
307330
if do_single_path_optimization:
308331
gc.set_foreground(tuple(edgecolors[0]))
309332
gc.set_linewidth(self._linewidths[0])
@@ -536,6 +559,42 @@ def set_linestyle(self, ls):
536559
self._linewidths, self._linestyles = self._bcast_lwls(
537560
self._us_lw, self._us_linestyles)
538561

562+
def set_capstyle(self, cs):
563+
"""
564+
Set the capstyle for the collection. The capstyle can
565+
only be set globally for all elements in the collection
566+
567+
Parameters
568+
----------
569+
cs : ['butt' | 'round' | 'projecting']
570+
The capstyle
571+
"""
572+
if cs in ('butt', 'round', 'projecting'):
573+
self._capstyle = cs
574+
else:
575+
raise ValueError('Unrecognized cap style. Found %s' % cs)
576+
577+
def get_capstyle(self):
578+
return self._capstyle
579+
580+
def set_joinstyle(self, js):
581+
"""
582+
Set the joinstyle for the collection. The joinstyle can only be
583+
set globally for all elements in the collection.
584+
585+
Parameters
586+
----------
587+
js : ['miter' | 'round' | 'bevel']
588+
The joinstyle
589+
"""
590+
if js in ('miter', 'round', 'bevel'):
591+
self._joinstyle = js
592+
else:
593+
raise ValueError('Unrecognized join style. Found %s' % js)
594+
595+
def get_joinstyle(self):
596+
return self._joinstyle
597+
539598
@staticmethod
540599
def _bcast_lwls(linewidths, dashes):
541600
'''Internal helper function to broadcast + scale ls/lw

lib/matplotlib/tests/test_collections.py

+39-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import matplotlib.pyplot as plt
1515
import matplotlib.collections as mcollections
1616
import matplotlib.transforms as mtransforms
17-
from matplotlib.collections import Collection, EventCollection
17+
from matplotlib.collections import Collection, LineCollection, EventCollection
1818
from matplotlib.testing.decorators import image_comparison
1919

2020

@@ -626,6 +626,44 @@ def test_lslw_bcast():
626626
assert_equal(col.get_linewidths(), [1, 2, 3])
627627

628628

629+
@pytest.mark.style('default')
630+
def test_capstyle():
631+
col = mcollections.PathCollection([], capstyle='round')
632+
assert_equal(col.get_capstyle(), 'round')
633+
col.set_capstyle('butt')
634+
assert_equal(col.get_capstyle(), 'butt')
635+
636+
637+
@pytest.mark.style('default')
638+
def test_joinstyle():
639+
col = mcollections.PathCollection([], joinstyle='round')
640+
assert_equal(col.get_joinstyle(), 'round')
641+
col.set_joinstyle('miter')
642+
assert_equal(col.get_joinstyle(), 'miter')
643+
644+
645+
@image_comparison(baseline_images=['cap_and_joinstyle'],
646+
extensions=['png'])
647+
def test_cap_and_joinstyle_image():
648+
fig = plt.figure()
649+
ax = fig.add_subplot(1, 1, 1)
650+
ax.set_xlim([-0.5, 1.5])
651+
ax.set_ylim([-0.5, 2.5])
652+
653+
x = np.array([0.0, 1.0, 0.5])
654+
ys = np.array([[0.0], [0.5], [1.0]]) + np.array([[0.0, 0.0, 1.0]])
655+
656+
segs = np.zeros((3, 3, 2))
657+
segs[:, :, 0] = x
658+
segs[:, :, 1] = ys
659+
line_segments = LineCollection(segs, linewidth=[10, 15, 20])
660+
line_segments.set_capstyle("round")
661+
line_segments.set_joinstyle("miter")
662+
663+
ax.add_collection(line_segments)
664+
ax.set_title('Line collection with customized caps and joinstyle')
665+
666+
629667
@image_comparison(baseline_images=['scatter_post_alpha'],
630668
extensions=['png'], remove_text=True,
631669
style='default')

0 commit comments

Comments
 (0)