diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 2cdb5117fb48..fb9c02427854 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1442,6 +1442,7 @@ def tk_window_focus(): 'matplotlib.tests.test_triangulation', 'mpl_toolkits.tests.test_mplot3d', 'matplotlib.tests.test_widgets', + 'matplotlib.tests.test_cycles', ] diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 4d10e8647e56..05502b1ac1a0 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -1271,7 +1271,9 @@ def plot(self, *args, **kwargs): By default, each line is assigned a different color specified by a 'color cycle'. To change this behavior, you can edit the - axes.color_cycle rcParam. + axes.color_cycle rcParam. Similarly, the default linestyle is + also specified by a 'linestyle cycle'. Edit the axes.linestyle_cycle + rcParam to specify a non-trivial cycle. The following format string characters are accepted to control the line style or marker: diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index eff223f92bb4..9a184660cb3e 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -140,6 +140,7 @@ def __init__(self, axes, command='plot'): self.axes = axes self.command = command self.set_color_cycle() + self.set_linestyle_cycle() def __getstate__(self): # note: it is not possible to pickle a itertools.cycle instance @@ -148,12 +149,18 @@ def __getstate__(self): def __setstate__(self, state): self.__dict__ = state.copy() self.set_color_cycle() + self.set_linestyle_cycle() def set_color_cycle(self, clist=None): if clist is None: clist = rcParams['axes.color_cycle'] self.color_cycle = itertools.cycle(clist) + def set_linestyle_cycle(self, clist=None): + if clist is None: + clist = rcParams['axes.linestyle_cycle'] + self.linestyle_cycle = itertools.cycle(clist) + def __call__(self, *args, **kwargs): if self.axes.xaxis is not None and self.axes.yaxis is not None: @@ -236,6 +243,8 @@ def _makeline(self, x, y, kw, kwargs): kw['color'] = six.next(self.color_cycle) # (can't use setdefault because it always evaluates # its second argument) + if 'linestyle' not in kw and 'linestyle' not in kwargs: + kw['linestyle'] = six.next(self.linestyle_cycle) seg = mlines.Line2D(x, y, axes=self.axes, **kw @@ -955,6 +964,14 @@ def set_color_cycle(self, clist): self._get_lines.set_color_cycle(clist) self._get_patches_for_fill.set_color_cycle(clist) + def set_linestyle_cycle(self, clist): + """ + Set the linestyle cycle for any future plot commands on this Axes. + + *clist* is a list of mpl linestyle specifiers. + """ + self._get_lines.set_linestyle_cycle(clist) + def ishold(self): """return the HOLD status of the axes""" return self._hold diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 67724f1e4c01..36cc45cd1fc0 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -612,6 +612,9 @@ def __call__(self, s): 'axes.color_cycle': [['b', 'g', 'r', 'c', 'm', 'y', 'k'], validate_colorlist], # cycle of plot # line colors + 'axes.linestyle_cycle': [['-'], + validate_stringlist], # cycle of plot + # line styles 'axes.xmargin': [0, ValidateInterval(0, 1, closedmin=True, closedmax=True)], # margin added to xaxis diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.pdf b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.pdf new file mode 100644 index 000000000000..9a6cb49ca871 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.pdf differ diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.png b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.png new file mode 100644 index 000000000000..583b7f9f7b1c Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.svg b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.svg new file mode 100644 index 000000000000..cbe0951bc566 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_cycles/color_cycle_basic.svg @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.pdf b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.pdf new file mode 100644 index 000000000000..1cc3a0c02a57 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.pdf differ diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.png b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.png new file mode 100644 index 000000000000..fe73deda63bc Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.svg b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.svg new file mode 100644 index 000000000000..12de1e387fee --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_cycles/linestyle_cycle_basic.svg @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_cycles.py b/lib/matplotlib/tests/test_cycles.py new file mode 100644 index 000000000000..2a3d60dc0379 --- /dev/null +++ b/lib/matplotlib/tests/test_cycles.py @@ -0,0 +1,48 @@ +import numpy as np + +from matplotlib.testing.decorators import image_comparison +import matplotlib.pyplot as plt + + +@image_comparison(baseline_images=['color_cycle_basic'], remove_text=True) +def test_colorcycle_basic(): + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_color_cycle(['r', 'g', 'y']) + xs = np.arange(10) + ys = 0.25 * xs + 2 + # Should be red + ax.plot(xs, ys) + # Should be green + ys = 0.45 * xs + 3 + ax.plot(xs, ys) + # Should be yellow + ys = 0.65 * xs + 4 + ax.plot(xs, ys) + # Should be red + ys = 0.85 * xs + 5 + ax.plot(xs, ys) + + +@image_comparison(baseline_images=['linestyle_cycle_basic'], remove_text=True) +def test_linestylecycle_basic(): + fig = plt.figure() + ax = fig.add_subplot(111) + ax.set_linestyle_cycle(['-', '--', ':']) + xs = np.arange(10) + # Should be solid + ys = 0.25 * xs + 2 + ax.plot(xs, ys) + # Should be dashed + ys = 0.45 * xs + 3 + ax.plot(xs, ys) + # Should be dotted + ys = 0.65 * xs + 4 + ax.plot(xs, ys) + # Should be solid + ys = 0.85 * xs + 5 + ax.plot(xs, ys) + +if __name__ == '__main__': + import nose + nose.runmodule(argv=['-s', '--with-doctest'], exit=False) diff --git a/matplotlibrc.template b/matplotlibrc.template index 89529327f4b6..8f459291fedd 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -79,8 +79,8 @@ backend : %(backend)s # See http://matplotlib.org/api/artist_api.html#module-matplotlib.lines for more # information on line properties. #lines.linewidth : 1.0 # line width in points -#lines.linestyle : - # solid line -#lines.color : blue # has no affect on plot(); see axes.color_cycle +#lines.linestyle : - # no affect on plot(); see axes.linestyle_cycle +#lines.color : blue # no affect on plot(); see axes.color_cycle #lines.marker : None # the default marker #lines.markeredgewidth : 0.5 # the line width around the marker symbol #lines.markersize : 6 # markersize, in points @@ -269,6 +269,10 @@ backend : %(backend)s # as list of string colorspecs: # single letter, long name, or # web-style hex +#axes.linestyle_cycle: - # linestyle cycle for plot lines as a list + # of string linestyle specs. Currently set to + # a single element list of '-' for backwards + # compatibility. #axes.xmargin : 0 # x margin. See `axes.Axes.margins` #axes.ymargin : 0 # y margin See `axes.Axes.margins`