8000 Shareable property cyclers. · matplotlib/matplotlib@3842d53 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3842d53

Browse files
committed
Shareable property cyclers.
Allow a single property cycler to be reused across multiple axes, with plots on any axes advancing the same joint iterator. e.g. ```python from matplotlib import pyplot as plt from matplotlib.axes._base import to_shareable_cycler shared = to_shareable_cycler(plt.rcParams["axes.prop_cycle"]) fig, axs = plt.subplots(2, sharex=True) axs[0].set_prop_cycle(shared) axs[1].set_prop_cycle(shared) axs[0].plot([0, 1]) axs[1].plot([0, 1]) # Check that fill uses a separate iterator. axs[1].fill([2, 3, 4], [0, 1, 0]) axs[0].fill([2, 3, 4], [0, 1, 0]) # Check that the second axes goes back to the first color, even though it # didn't use it on the first cycle. for i in range(10): axs[1].plot([5+i, 5+i], [0, 1]) plt.show() ```
1 parent e884db3 commit 3842d53

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,38 @@ def _process_plot_format(fmt):
207207
return linestyle, marker, color
208208

209209

210+
def to_shareable_cycler(cycler):
211+
"""
212+
Return a copy of *cycler*, that can be shared across multiple Axes.
213+
214+
Plotting on any Axes will advance the joint property iterators of all Axes.
215+
"""
216+
from cycler import Cycler
217+
new = Cycler(cycler)
218+
# This doesn't carry forward any previous shares, but that can easily be
219+
# changed by checking first whether the dict exists.
220+
new._cycling_iterators_cache = {}
221+
return new
222+
223+
224+
def _get_cycling_iterator(cycler, name):
225+
"""
226+
Return an `itertools.cycle()` over this *cycler*, intended for plotting
227+
command *name*.
228+
229+
If this cycler is shareable (per `to_shareable_cycler`), then multiple
230+
invocations with the same *cycler* and *name* will return the same
231+
`itertools.cycle` instance (*name* only serves as a key for this purpose).
232+
If this cycler is not shareable, then a new `itertools.cycle` instance is
233+
returned every time.
234+
"""
235+
if not hasattr(cycler, "_cycling_iterators_cache"):
236+
return itertools.cycle(cycler)
237+
if name not in cycler._cycling_iterators_cache:
238+
cycler._cycling_iterators_cache[name] = itertools.cycle(cycler)
239+
return cycler._cycling_iterators_cache[name]
240+
241+
210242
class _process_plot_var_args:
211243
"""
212244
Process variable length arguments to `~.Axes.plot`, to support ::
@@ -234,7 +266,7 @@ def __setstate__(self, state):
234266
def set_prop_cycle(self, cycler):
235267
if cycler is None:
236268
cycler = mpl.rcParams['axes.prop_cycle']
237-
self.prop_cycler = itertools.cycle(cycler)
269+
self.prop_cycler = _get_cycling_iterator(cycler, self.command)
238270
self._prop_keys = cycler.keys # This should make a copy
239271

240272
def __call__(self, *args, data=None, **kwargs):

0 commit comments

Comments
 (0)
0