diff --git a/.gitignore b/.gitignore index a36f555e4..7c1d0fa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +ultraplot/tests/baseline # VIM extras .session.vim .vimsession diff --git a/ultraplot/axes/plot.py b/ultraplot/axes/plot.py index 17da6e2e0..bbba324ca 100644 --- a/ultraplot/axes/plot.py +++ b/ultraplot/axes/plot.py @@ -2477,54 +2477,43 @@ def _parse_cycle( Whether to simply return the property cycle or apply it. The cycle is only applied (and therefore reset) if it differs from the current one. """ - # Create the property cycler and update it if necessary - # NOTE: Matplotlib Cycler() objects have built-in __eq__ operator - # so really easy to check if the cycler has changed! - if cycle is not None or cycle_kw: - cycle_kw = cycle_kw or {} - if ncycle != 1: # ignore for column-by-column plotting commands - cycle_kw.setdefault("N", ncycle) # if None then filled in Colormap() - if isinstance(cycle, str) and cycle.lower() == "none": - cycle = False - if not cycle: - args = () - elif cycle is True: # consistency with 'False' ('reactivate' the cycler) - args = (rc["axes.prop_cycle"],) - else: - args = (cycle,) - cycle = constructor.Cycle(*args, **cycle_kw) - with warnings.catch_warnings(): # hide 'elementwise-comparison failed' - warnings.simplefilter("ignore", FutureWarning) - if return_cycle: - pass - elif cycle != self._active_cycle: - self.set_prop_cycle(cycle) - - # Manually extract and apply settings to outgoing keyword arguments - # if native matplotlib function does not include desired properties + cycle_kw = cycle_kw or {} cycle_manually = cycle_manually or {} - parser = self._get_lines # the _process_plot_var_args instance - props = {} # which keys to apply from property cycler - # BREAKING in mpl3.9.1 parse has cycle items and no longer posseses _prop_keys - for prop, key in cycle_manually.items(): - if kwargs.get(key, None) is None and any( - prop in item for item in parser._cycler_items - ): - props[prop] = key - if props: - for dict_ in parser._cycler_items: - for prop, key in props.items(): - value = dict_[prop] - if ( - key == "c" - ): # special case: scatter() color must be converted to hex - value = pcolors.to_hex(value) - kwargs[key] = value - + cycle_kw.setdefault("N", ncycle) + + # Match-case for cycle resolution + match cycle: + case None if not cycle_kw: + resolved_cycle = None + case True: + resolved_cycle = constructor.Cycle(rc["axes.prop_cycle"]) + case str() if cycle.lower() == "none": + resolved_cycle = None + case str() | int(): + resolved_cycle = constructor.Cycle(cycle, **cycle_kw) + case _: + resolved_cycle = None + + # Ignore cycle for single-column plotting + resolved_cycle = None if ncycle == 1 else resolved_cycle + + # Return or apply cycle if return_cycle: - return cycle, kwargs # needed for stem() to apply in a context() - else: - return kwargs + return resolved_cycle, kwargs + + if resolved_cycle and resolved_cycle != self._active_cycle: + self.set_prop_cycle(resolved_cycle) + + # Apply manual cycle properties + if cycle_manually: + current_prop = self._get_lines._cycler_items[self._get_lines._idx] + self._get_lines._idx = (self._get_lines._idx + 1) % len(self._active_cycle) + for prop, key in cycle_manually.items(): + if kwargs.get(key) is None and prop in current_prop: + value = current_prop[prop] + kwargs[key] = pcolors.to_rgba(value) if key == "c" else value + + return kwargs def _parse_level_lim( self, @@ -3459,12 +3448,9 @@ def _apply_scatter(self, xs, ys, ss, cc, *, vert=True, **kwargs): ys, kw = inputs._dist_reduce(ys, **kw) ss, kw = self._parse_markersize(ss, **kw) # parse 's' - # Move _parse_cycle before _parse_color - kw = self._parse_cycle(xs.shape[1] if xs.ndim > 1 else 1, **kw) - # Only parse color if explicitly provided + infer_rgb = True if cc is not None: - infer_rgb = True if not isinstance(cc, str): test = np.atleast_1d(cc) if ( @@ -3482,14 +3468,14 @@ def _apply_scatter(self, xs, ys, ss, cc, *, vert=True, **kwargs): infer_rgb=infer_rgb, **kw, ) - + # Create the cycler object by manually cycling and sanitzing the inputs guide_kw = _pop_params(kw, self._update_guide) objs = [] for _, n, x, y, s, c, kw in self._iter_arg_cols(xs, ys, ss, cc, **kw): - # Don't set 'c' explicitly unless it was provided - kw["s"] = s - if c is not None: - kw["c"] = c + # Cycle s and c as they are in cycle_manually + # Note: they could be None + kw["s"], kw["c"] = s, c + kw = self._parse_cycle(n, cycle_manually=cycle_manually, **kw) *eb, kw = self._add_error_bars(x, y, vert=vert, default_barstds=True, **kw) *es, kw = self._add_error_shading(x, y, vert=vert, color_key="c", **kw) if not vert: @@ -4029,6 +4015,7 @@ def _apply_violinplot( bodies = artists.pop("bodies", ()) # should be no other entries if bodies: bodies = cbook.silent_list(type(bodies[0]).__name__, bodies) + for i, body in enumerate(bodies): body.set_alpha(1.0) # change default to 1.0 if fillcolor[i] is not None: diff --git a/ultraplot/constructor.py b/ultraplot/constructor.py index 4ed08cdc8..f3df94e09 100644 --- a/ultraplot/constructor.py +++ b/ultraplot/constructor.py @@ -30,7 +30,13 @@ from . import ticker as pticker from .config import rc from .internals import ic # noqa: F401 -from .internals import _not_none, _pop_props, _version_cartopy, _version_mpl, warnings +from .internals import ( + _not_none, + _pop_props, + _version_cartopy, + _version_mpl, + warnings, +) from .utils import get_colors, to_hex, to_rgba try: @@ -235,7 +241,12 @@ "height": 15000e3, }, "tmerc": {"lon_0": 0, "lat_0": 0, "width": 10000e3, "height": 10000e3}, - "merc": {"llcrnrlat": -80, "urcrnrlat": 84, "llcrnrlon": -180, "urcrnrlon": 180}, + "merc": { + "llcrnrlat": -80, + "urcrnrlat": 84, + "llcrnrlon": -180, + "urcrnrlon": 180, + }, "omerc": { "lat_0": 0, "lon_0": 0, @@ -762,9 +773,9 @@ def _pop_modification(key): return cmap -def Cycle(*args, N=None, samples=None, name=None, **kwargs): +class Cycle(cycler.Cycler): """ - Generate and merge `~cycler.Cycler` instances in a variety of ways. + Generate and merge `~cycler.Cycler` instances in a variety of ways. The new generated class can be used to internally map keywords to the properties of the `~cycler.Cycler` instance. It is used by various plot functions to cycle through colors, linestyles, markers, etc. Parameters ---------- @@ -777,12 +788,12 @@ def Cycle(*args, N=None, samples=None, name=None, **kwargs): * If a `~cycler.Cycler`, nothing more is done. * If a sequence of RGB tuples or color strings, these colors are used. * If a `~ultraplot.colors.DiscreteColormap`, colors from the ``colors`` - attribute are used. + attribute are used. * If a string cycle name, that `~ultraplot.colors.DiscreteColormap` - is looked up and its ``colors`` are used. + is looked up and its ``colors`` are used. * In all other cases, the argument is passed to `Colormap`, and - colors from the resulting `~ultraplot.colors.ContinuousColormap` - are used. See the `samples` argument. + colors from the resulting `~ultraplot.colors.ContinuousColormap` + are used. See the `samples` argument. If the last positional argument is numeric, it is used for the `samples` keyword argument. @@ -830,12 +841,6 @@ def Cycle(*args, N=None, samples=None, name=None, **kwargs): to `Colormap` and used to build the `~ultraplot.colors.DiscreteColormap` from which the cycler will draw its colors. - Returns - ------- - cycler.Cycler - A `~cycler.Cycler` instance that can be passed - to `~matplotlib.axes.Axes.set_prop_cycle`. - See also -------- cycler.cycler @@ -845,65 +850,103 @@ def Cycle(*args, N=None, samples=None, name=None, **kwargs): ultraplot.constructor.Norm ultraplot.utils.get_colors """ - # Parse keyword arguments that rotate through other properties - # besides color cycles. - props = _pop_props(kwargs, "line") - if "sizes" in kwargs: # special case, gets translated back by scatter() - props.setdefault("markersize", kwargs.pop("sizes")) - samples = _not_none(samples=samples, N=N) # trigger Colormap default - for key, value in tuple(props.items()): # permit in-place modification - if value is None: - return - elif not np.iterable(value) or isinstance(value, str): - value = (value,) - props[key] = list(value) # ensure mutable list - # If args is non-empty, means we want color cycle; otherwise is black - if not args: - props.setdefault("color", ["black"]) + def __init__(self, *args, N=None, samples=None, name=None, **kwargs): + self.name = "_no_name" # default value + cycler_props = self._parse_basic_properties(kwargs) + samples = _not_none(samples=samples, N=N) # trigger Colormap default + if not args: + self._handle_empty_args(cycler_props, kwargs) + elif self._is_all_cyclers(args): + self._handle_cycler_args(args, cycler_props, kwargs) + else: + self._handle_colormap_args(args, cycler_props, kwargs, samples, name) + + self._iterator = None # internal reference for cycle + + def _parse_basic_properties(self, kwargs): + """Parse and validate basic properties from kwargs.""" + props = _pop_props(kwargs, "line") + if "sizes" in kwargs: + props.setdefault("markersize", kwargs.pop("sizes")) + + for key, value in tuple(props.items()): + if value is None: + props[key] = ["black"] # default instead of early return + elif not np.iterable(value) or isinstance(value, str): + props[key] = [value] + else: + props[key] = list(value) # ensure mutable list + return props + + def _handle_empty_args(self, props, kwargs): + """Handle case when no positional arguments are provided.""" + props.setdefault("color", "black") if kwargs: warnings._warn_ultraplot(f"Ignoring Cycle() keyword arg(s) {kwargs}.") - dicts = () + self._build_cycler(()) - # Merge cycler objects and/or update cycler objects with input kwargs - elif all(isinstance(arg, cycler.Cycler) for arg in args): + def _handle_cycler_args(self, args, props, kwargs): + """Handle case when arguments are cycler objects.""" if kwargs: warnings._warn_ultraplot(f"Ignoring Cycle() keyword arg(s) {kwargs}.") if len(args) == 1 and not props: - return args[0] - dicts = tuple(arg.by_key() for arg in args) + self._build_cycler((args[0].by_key(),)) + else: + dicts = tuple(arg.by_key() for arg in args) + self._build_cycler(dicts + (props,)) - # Get a cycler from a colormap - # NOTE: Passing discrete=True does not imply default_luminance=90 because - # someone might be trying to make qualitative colormap for use in 2D plot - else: + def _handle_colormap_args(self, args, props, kwargs, samples, name): + """Handle case when arguments are for creating a colormap.""" if isinstance(args[-1], Number): args, samples = args[:-1], _not_none( samples_positional=args[-1], samples=samples - ) # noqa: #501 + ) + + cmap = self._create_colormap(args, name, samples, kwargs) + dict_ = {"color": [c if isinstance(c, str) else to_hex(c) for c in cmap.colors]} + self._build_cycler((dict_, props)) + self.name = _not_none(name, cmap.name) + + def _create_colormap(self, args, name, samples, kwargs): + """Create a colormap from the given arguments.""" kwargs.setdefault("listmode", "discrete") kwargs.setdefault("filemode", "discrete") - kwargs["discrete"] = True # triggers application of default 'samples' + kwargs["discrete"] = True kwargs["default_luminance"] = DEFAULT_CYCLE_LUMINANCE - cmap = Colormap(*args, name=name, samples=samples, **kwargs) - name = _not_none(name, cmap.name) - dict_ = {"color": [c if isinstance(c, str) else to_hex(c) for c in cmap.colors]} - dicts = (dict_,) - - # Update the cyler property - dicts = dicts + (props,) - props = {} - for dict_ in dicts: - for key, value in dict_.items(): - props.setdefault(key, []).extend(value) - - # Build cycler with matching property lengths - maxlen = np.lcm.reduce([len(value) for value in props.values()]) - props = {key: value * (maxlen // len(value)) for key, value in props.items()} - cycle = cycler.cycler(**props) - cycle.name = _not_none(name, "_no_name") - - return cycle + return Colormap(*args, name=name, samples=samples, **kwargs) + + def _is_all_cyclers(self, args): + """Check if all arguments are Cycler objects.""" + return all(isinstance(arg, cycler.Cycler) for arg in args) + + def _build_cycler(self, dicts): + """Build the final cycler from the given dictionaries.""" + props = {} + for dict_ in dicts: + for key, value in dict_.items(): + props.setdefault(key, []).extend(value) + # Build cycler with matching property lengths + # Ensure at least a default color property exists + if not props: + props = {"color": ["black"]} + + # Build cycler with matching property lengths + lengths = [len(value) for value in props.values()] + maxlen = np.lcm.reduce(lengths) + props = {key: value * (maxlen // len(value)) for key, value in props.items()} + mcycler = cycler.cycler(**props) + super().__init__(mcycler) + + def get_next(self): + # Get the next set of properties + if self._iterator is None: + self._iterator = iter(self) + try: + return next(self._iterator) + except StopIteration: + self._iterator = iter(self) + return next(self._iterator) def Norm(norm, *args, **kwargs): diff --git a/ultraplot/tests/baseline/test_align_labels.png b/ultraplot/tests/baseline/test_align_labels.png deleted file mode 100644 index db69f10b7..000000000 Binary files a/ultraplot/tests/baseline/test_align_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_aligned_outer_guides.png b/ultraplot/tests/baseline/test_aligned_outer_guides.png deleted file mode 100644 index b3747bd22..000000000 Binary files a/ultraplot/tests/baseline/test_aligned_outer_guides.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_aspect_ratios.png b/ultraplot/tests/baseline/test_aspect_ratios.png deleted file mode 100644 index 31722d6b8..000000000 Binary files a/ultraplot/tests/baseline/test_aspect_ratios.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_auto_diverging1.png b/ultraplot/tests/baseline/test_auto_diverging1.png deleted file mode 100644 index 74f63e2c5..000000000 Binary files a/ultraplot/tests/baseline/test_auto_diverging1.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_auto_legend.png b/ultraplot/tests/baseline/test_auto_legend.png deleted file mode 100644 index 13e07b08f..000000000 Binary files a/ultraplot/tests/baseline/test_auto_legend.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_auto_reverse.png b/ultraplot/tests/baseline/test_auto_reverse.png deleted file mode 100644 index 19c72c6f9..000000000 Binary files a/ultraplot/tests/baseline/test_auto_reverse.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_autodiverging3.png b/ultraplot/tests/baseline/test_autodiverging3.png deleted file mode 100644 index f0887af98..000000000 Binary files a/ultraplot/tests/baseline/test_autodiverging3.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_autodiverging4.png b/ultraplot/tests/baseline/test_autodiverging4.png deleted file mode 100644 index 6329e532b..000000000 Binary files a/ultraplot/tests/baseline/test_autodiverging4.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_autodiverging5.png b/ultraplot/tests/baseline/test_autodiverging5.png deleted file mode 100644 index 40830d046..000000000 Binary files a/ultraplot/tests/baseline/test_autodiverging5.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_axes_colors.png b/ultraplot/tests/baseline/test_axes_colors.png deleted file mode 100644 index 26d38cfe2..000000000 Binary files a/ultraplot/tests/baseline/test_axes_colors.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_bar_vectors.png b/ultraplot/tests/baseline/test_bar_vectors.png deleted file mode 100644 index e444f3915..000000000 Binary files a/ultraplot/tests/baseline/test_bar_vectors.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_bar_width.png b/ultraplot/tests/baseline/test_bar_width.png deleted file mode 100644 index 1034131c8..000000000 Binary files a/ultraplot/tests/baseline/test_bar_width.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_both_ticklabels.png b/ultraplot/tests/baseline/test_both_ticklabels.png deleted file mode 100644 index 4039f59fb..000000000 Binary files a/ultraplot/tests/baseline/test_both_ticklabels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_bounds_ticks.png b/ultraplot/tests/baseline/test_bounds_ticks.png deleted file mode 100644 index 3d340eefd..000000000 Binary files a/ultraplot/tests/baseline/test_bounds_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_boxplot_colors.png b/ultraplot/tests/baseline/test_boxplot_colors.png deleted file mode 100644 index d8f6cf8ec..000000000 Binary files a/ultraplot/tests/baseline/test_boxplot_colors.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_boxplot_vectors.png b/ultraplot/tests/baseline/test_boxplot_vectors.png deleted file mode 100644 index 096c55c1a..000000000 Binary files a/ultraplot/tests/baseline/test_boxplot_vectors.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_cartopy_contours.png b/ultraplot/tests/baseline/test_cartopy_contours.png deleted file mode 100644 index 022544508..000000000 Binary files a/ultraplot/tests/baseline/test_cartopy_contours.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_cartopy_labels.png b/ultraplot/tests/baseline/test_cartopy_labels.png deleted file mode 100644 index 5a37a94f6..000000000 Binary files a/ultraplot/tests/baseline/test_cartopy_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_cartopy_manual.png b/ultraplot/tests/baseline/test_cartopy_manual.png deleted file mode 100644 index ed25f8a0d..000000000 Binary files a/ultraplot/tests/baseline/test_cartopy_manual.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_centered_legends.png b/ultraplot/tests/baseline/test_centered_legends.png deleted file mode 100644 index d513322c7..000000000 Binary files a/ultraplot/tests/baseline/test_centered_legends.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_cmap_cycles.png b/ultraplot/tests/baseline/test_cmap_cycles.png deleted file mode 100644 index 7e303890f..000000000 Binary files a/ultraplot/tests/baseline/test_cmap_cycles.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_colorbar.png b/ultraplot/tests/baseline/test_colorbar.png deleted file mode 100644 index c5ce770f9..000000000 Binary files a/ultraplot/tests/baseline/test_colorbar.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_colorbar_ticks.png b/ultraplot/tests/baseline/test_colorbar_ticks.png deleted file mode 100644 index 3e7ea44e4..000000000 Binary files a/ultraplot/tests/baseline/test_colorbar_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_colormap_mode.png b/ultraplot/tests/baseline/test_colormap_mode.png deleted file mode 100644 index ee45d3a69..000000000 Binary files a/ultraplot/tests/baseline/test_colormap_mode.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_column_iteration.png b/ultraplot/tests/baseline/test_column_iteration.png deleted file mode 100644 index 142d1986f..000000000 Binary files a/ultraplot/tests/baseline/test_column_iteration.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_complex_ticks.png b/ultraplot/tests/baseline/test_complex_ticks.png deleted file mode 100644 index d3fc539c4..000000000 Binary files a/ultraplot/tests/baseline/test_complex_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_contour_labels.png b/ultraplot/tests/baseline/test_contour_labels.png deleted file mode 100644 index c5de493f5..000000000 Binary files a/ultraplot/tests/baseline/test_contour_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_contour_legend_with_label.png b/ultraplot/tests/baseline/test_contour_legend_with_label.png deleted file mode 100644 index 3fc406ca7..000000000 Binary files a/ultraplot/tests/baseline/test_contour_legend_with_label.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_contour_legend_without_label.png b/ultraplot/tests/baseline/test_contour_legend_without_label.png deleted file mode 100644 index 189be39b4..000000000 Binary files a/ultraplot/tests/baseline/test_contour_legend_without_label.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_contour_negative.png b/ultraplot/tests/baseline/test_contour_negative.png deleted file mode 100644 index 40d3b6553..000000000 Binary files a/ultraplot/tests/baseline/test_contour_negative.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_contour_single.png b/ultraplot/tests/baseline/test_contour_single.png deleted file mode 100644 index 00c5c49b5..000000000 Binary files a/ultraplot/tests/baseline/test_contour_single.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_cutoff_ticks.png b/ultraplot/tests/baseline/test_cutoff_ticks.png deleted file mode 100644 index 9e86a4016..000000000 Binary files a/ultraplot/tests/baseline/test_cutoff_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_data_keyword.png b/ultraplot/tests/baseline/test_data_keyword.png deleted file mode 100644 index 561eb0a4d..000000000 Binary files a/ultraplot/tests/baseline/test_data_keyword.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_discrete_ticks.png b/ultraplot/tests/baseline/test_discrete_ticks.png deleted file mode 100644 index 9be5e5848..000000000 Binary files a/ultraplot/tests/baseline/test_discrete_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_discrete_vs_fixed.png b/ultraplot/tests/baseline/test_discrete_vs_fixed.png deleted file mode 100644 index 94eece11a..000000000 Binary files a/ultraplot/tests/baseline/test_discrete_vs_fixed.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_drawing_in_projection_with_globe.png b/ultraplot/tests/baseline/test_drawing_in_projection_with_globe.png deleted file mode 100644 index 6be3c8a6b..000000000 Binary files a/ultraplot/tests/baseline/test_drawing_in_projection_with_globe.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_drawing_in_projection_without_globe.png b/ultraplot/tests/baseline/test_drawing_in_projection_without_globe.png deleted file mode 100644 index 90aa802a0..000000000 Binary files a/ultraplot/tests/baseline/test_drawing_in_projection_without_globe.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_edge_fix.png b/ultraplot/tests/baseline/test_edge_fix.png deleted file mode 100644 index d2d277ef0..000000000 Binary files a/ultraplot/tests/baseline/test_edge_fix.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_flow_functions.png b/ultraplot/tests/baseline/test_flow_functions.png deleted file mode 100644 index 4681deffa..000000000 Binary files a/ultraplot/tests/baseline/test_flow_functions.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_font_adjustments.png b/ultraplot/tests/baseline/test_font_adjustments.png deleted file mode 100644 index f199220cf..000000000 Binary files a/ultraplot/tests/baseline/test_font_adjustments.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_geographic_multiple_projections.png b/ultraplot/tests/baseline/test_geographic_multiple_projections.png deleted file mode 100644 index 3c586bb5d..000000000 Binary files a/ultraplot/tests/baseline/test_geographic_multiple_projections.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_geographic_single_projection.png b/ultraplot/tests/baseline/test_geographic_single_projection.png deleted file mode 100644 index 59ee9698d..000000000 Binary files a/ultraplot/tests/baseline/test_geographic_single_projection.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_gray_adjustment.png b/ultraplot/tests/baseline/test_gray_adjustment.png deleted file mode 100644 index 98e519f57..000000000 Binary files a/ultraplot/tests/baseline/test_gray_adjustment.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_histogram_legend.png b/ultraplot/tests/baseline/test_histogram_legend.png deleted file mode 100644 index 665a601e3..000000000 Binary files a/ultraplot/tests/baseline/test_histogram_legend.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_histogram_types.png b/ultraplot/tests/baseline/test_histogram_types.png deleted file mode 100644 index bd3757445..000000000 Binary files a/ultraplot/tests/baseline/test_histogram_types.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_ignore_message.png b/ultraplot/tests/baseline/test_ignore_message.png deleted file mode 100644 index f2f8b06e5..000000000 Binary files a/ultraplot/tests/baseline/test_ignore_message.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inbounds_data.png b/ultraplot/tests/baseline/test_inbounds_data.png deleted file mode 100644 index ea95650fd..000000000 Binary files a/ultraplot/tests/baseline/test_inbounds_data.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_init_format.png b/ultraplot/tests/baseline/test_init_format.png deleted file mode 100644 index ee2f96d13..000000000 Binary files a/ultraplot/tests/baseline/test_init_format.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inner_title_zorder.png b/ultraplot/tests/baseline/test_inner_title_zorder.png deleted file mode 100644 index eef2dae0b..000000000 Binary files a/ultraplot/tests/baseline/test_inner_title_zorder.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inset_basic.png b/ultraplot/tests/baseline/test_inset_basic.png deleted file mode 100644 index a2036b2b4..000000000 Binary files a/ultraplot/tests/baseline/test_inset_basic.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inset_colorbars.png b/ultraplot/tests/baseline/test_inset_colorbars.png deleted file mode 100644 index dbd530114..000000000 Binary files a/ultraplot/tests/baseline/test_inset_colorbars.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inset_colors_1.png b/ultraplot/tests/baseline/test_inset_colors_1.png deleted file mode 100644 index cb30a77ce..000000000 Binary files a/ultraplot/tests/baseline/test_inset_colors_1.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inset_colors_2.png b/ultraplot/tests/baseline/test_inset_colors_2.png deleted file mode 100644 index 6d1123ad3..000000000 Binary files a/ultraplot/tests/baseline/test_inset_colors_2.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_inset_zoom_update.png b/ultraplot/tests/baseline/test_inset_zoom_update.png deleted file mode 100644 index 3bc68f11d..000000000 Binary files a/ultraplot/tests/baseline/test_inset_zoom_update.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_invalid_dist.png b/ultraplot/tests/baseline/test_invalid_dist.png deleted file mode 100644 index 3f86f61a6..000000000 Binary files a/ultraplot/tests/baseline/test_invalid_dist.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_invalid_plot.png b/ultraplot/tests/baseline/test_invalid_plot.png deleted file mode 100644 index 3cce61f36..000000000 Binary files a/ultraplot/tests/baseline/test_invalid_plot.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_keep_guide_labels.png b/ultraplot/tests/baseline/test_keep_guide_labels.png deleted file mode 100644 index 97f5937cc..000000000 Binary files a/ultraplot/tests/baseline/test_keep_guide_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_label_settings.png b/ultraplot/tests/baseline/test_label_settings.png deleted file mode 100644 index cbdc5bf96..000000000 Binary files a/ultraplot/tests/baseline/test_label_settings.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_level_restriction.png b/ultraplot/tests/baseline/test_level_restriction.png deleted file mode 100644 index fadd5015f..000000000 Binary files a/ultraplot/tests/baseline/test_level_restriction.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_levels_with_vmin_vmax.png b/ultraplot/tests/baseline/test_levels_with_vmin_vmax.png deleted file mode 100644 index 8ec6a5b8e..000000000 Binary files a/ultraplot/tests/baseline/test_levels_with_vmin_vmax.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_locale_formatting.png b/ultraplot/tests/baseline/test_locale_formatting.png deleted file mode 100644 index 5e1562c53..000000000 Binary files a/ultraplot/tests/baseline/test_locale_formatting.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_locale_formatting_en_US.UTF-8.png b/ultraplot/tests/baseline/test_locale_formatting_en_US.UTF-8.png deleted file mode 100644 index 8c266d78b..000000000 Binary files a/ultraplot/tests/baseline/test_locale_formatting_en_US.UTF-8.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_manual_labels.png b/ultraplot/tests/baseline/test_manual_labels.png deleted file mode 100644 index 13d57e563..000000000 Binary files a/ultraplot/tests/baseline/test_manual_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_multi_formatting.png b/ultraplot/tests/baseline/test_multi_formatting.png deleted file mode 100644 index a0a71d22c..000000000 Binary files a/ultraplot/tests/baseline/test_multi_formatting.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_multiple_calls.png b/ultraplot/tests/baseline/test_multiple_calls.png deleted file mode 100644 index f74de92c3..000000000 Binary files a/ultraplot/tests/baseline/test_multiple_calls.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_on_the_fly_mappable.png b/ultraplot/tests/baseline/test_on_the_fly_mappable.png deleted file mode 100644 index e57ec809e..000000000 Binary files a/ultraplot/tests/baseline/test_on_the_fly_mappable.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_outer_align.png b/ultraplot/tests/baseline/test_outer_align.png deleted file mode 100644 index c551af339..000000000 Binary files a/ultraplot/tests/baseline/test_outer_align.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_panel_dist.png b/ultraplot/tests/baseline/test_panel_dist.png deleted file mode 100644 index 34dda7b59..000000000 Binary files a/ultraplot/tests/baseline/test_panel_dist.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_panels_suplabels_three_hor_panels.png b/ultraplot/tests/baseline/test_panels_suplabels_three_hor_panels.png deleted file mode 100644 index 1e6dc9649..000000000 Binary files a/ultraplot/tests/baseline/test_panels_suplabels_three_hor_panels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_panels_with_sharing.png b/ultraplot/tests/baseline/test_panels_with_sharing.png deleted file mode 100644 index ddaa29691..000000000 Binary files a/ultraplot/tests/baseline/test_panels_with_sharing.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_panels_without_sharing_1.png b/ultraplot/tests/baseline/test_panels_without_sharing_1.png deleted file mode 100644 index 18d953265..000000000 Binary files a/ultraplot/tests/baseline/test_panels_without_sharing_1.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_panels_without_sharing_2.png b/ultraplot/tests/baseline/test_panels_without_sharing_2.png deleted file mode 100644 index c8acf5d66..000000000 Binary files a/ultraplot/tests/baseline/test_panels_without_sharing_2.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_parametric_colors.png b/ultraplot/tests/baseline/test_parametric_colors.png deleted file mode 100644 index 38fb4d555..000000000 Binary files a/ultraplot/tests/baseline/test_parametric_colors.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_parametric_labels.png b/ultraplot/tests/baseline/test_parametric_labels.png deleted file mode 100644 index 3c7f439ec..000000000 Binary files a/ultraplot/tests/baseline/test_parametric_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_patch_format.png b/ultraplot/tests/baseline/test_patch_format.png deleted file mode 100644 index 1dd8acb07..000000000 Binary files a/ultraplot/tests/baseline/test_patch_format.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_pie_charts.png b/ultraplot/tests/baseline/test_pie_charts.png deleted file mode 100644 index 37d744e41..000000000 Binary files a/ultraplot/tests/baseline/test_pie_charts.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_pint_quantities.png b/ultraplot/tests/baseline/test_pint_quantities.png deleted file mode 100644 index 828711cce..000000000 Binary files a/ultraplot/tests/baseline/test_pint_quantities.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_polar_projections.png b/ultraplot/tests/baseline/test_polar_projections.png deleted file mode 100644 index 246d349ca..000000000 Binary files a/ultraplot/tests/baseline/test_polar_projections.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_projection_dicts.png b/ultraplot/tests/baseline/test_projection_dicts.png deleted file mode 100644 index 4d289135a..000000000 Binary files a/ultraplot/tests/baseline/test_projection_dicts.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_qualitative_colormaps_1.png b/ultraplot/tests/baseline/test_qualitative_colormaps_1.png deleted file mode 100644 index c1d5790b6..000000000 Binary files a/ultraplot/tests/baseline/test_qualitative_colormaps_1.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_qualitative_colormaps_2.png b/ultraplot/tests/baseline/test_qualitative_colormaps_2.png deleted file mode 100644 index 2b170e550..000000000 Binary files a/ultraplot/tests/baseline/test_qualitative_colormaps_2.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_reversed_levels.png b/ultraplot/tests/baseline/test_reversed_levels.png deleted file mode 100644 index c0c3401f3..000000000 Binary files a/ultraplot/tests/baseline/test_reversed_levels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_scatter_alpha.png b/ultraplot/tests/baseline/test_scatter_alpha.png deleted file mode 100644 index 74b09e100..000000000 Binary files a/ultraplot/tests/baseline/test_scatter_alpha.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_scatter_args.png b/ultraplot/tests/baseline/test_scatter_args.png deleted file mode 100644 index 9cc127b0a..000000000 Binary files a/ultraplot/tests/baseline/test_scatter_args.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_scatter_cycle.png b/ultraplot/tests/baseline/test_scatter_cycle.png deleted file mode 100644 index 288525e86..000000000 Binary files a/ultraplot/tests/baseline/test_scatter_cycle.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_scatter_inbounds.png b/ultraplot/tests/baseline/test_scatter_inbounds.png deleted file mode 100644 index d4f5cb4ba..000000000 Binary files a/ultraplot/tests/baseline/test_scatter_inbounds.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_scatter_sizes.png b/ultraplot/tests/baseline/test_scatter_sizes.png deleted file mode 100644 index 9be18facb..000000000 Binary files a/ultraplot/tests/baseline/test_scatter_sizes.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_seaborn_heatmap.png b/ultraplot/tests/baseline/test_seaborn_heatmap.png deleted file mode 100644 index ebc2abf9c..000000000 Binary files a/ultraplot/tests/baseline/test_seaborn_heatmap.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_seaborn_hist.png b/ultraplot/tests/baseline/test_seaborn_hist.png deleted file mode 100644 index 47e0dcb4c..000000000 Binary files a/ultraplot/tests/baseline/test_seaborn_hist.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_seaborn_relational.png b/ultraplot/tests/baseline/test_seaborn_relational.png deleted file mode 100644 index bc9b210ca..000000000 Binary files a/ultraplot/tests/baseline/test_seaborn_relational.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_seaborn_swarmplot.png b/ultraplot/tests/baseline/test_seaborn_swarmplot.png deleted file mode 100644 index 5dd172348..000000000 Binary files a/ultraplot/tests/baseline/test_seaborn_swarmplot.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_segmented_norm.png b/ultraplot/tests/baseline/test_segmented_norm.png deleted file mode 100644 index e8f04aef7..000000000 Binary files a/ultraplot/tests/baseline/test_segmented_norm.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_segmented_norm_ticks.png b/ultraplot/tests/baseline/test_segmented_norm_ticks.png deleted file mode 100644 index b8e116768..000000000 Binary files a/ultraplot/tests/baseline/test_segmented_norm_ticks.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_share_all_basic.png b/ultraplot/tests/baseline/test_share_all_basic.png deleted file mode 100644 index fc1db6a4f..000000000 Binary files a/ultraplot/tests/baseline/test_share_all_basic.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_singleton_legend.png b/ultraplot/tests/baseline/test_singleton_legend.png deleted file mode 100644 index d3030b155..000000000 Binary files a/ultraplot/tests/baseline/test_singleton_legend.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_span_labels.png b/ultraplot/tests/baseline/test_span_labels.png deleted file mode 100644 index 711569271..000000000 Binary files a/ultraplot/tests/baseline/test_span_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_spine_offset.png b/ultraplot/tests/baseline/test_spine_offset.png deleted file mode 100644 index 625cc83df..000000000 Binary files a/ultraplot/tests/baseline/test_spine_offset.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_spine_side.png b/ultraplot/tests/baseline/test_spine_side.png deleted file mode 100644 index a0811b580..000000000 Binary files a/ultraplot/tests/baseline/test_spine_side.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_standardized_input.png b/ultraplot/tests/baseline/test_standardized_input.png deleted file mode 100644 index 2f6be9b85..000000000 Binary files a/ultraplot/tests/baseline/test_standardized_input.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_statistical_boxplot.png b/ultraplot/tests/baseline/test_statistical_boxplot.png deleted file mode 100644 index c586bf0a5..000000000 Binary files a/ultraplot/tests/baseline/test_statistical_boxplot.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_three_axes.png b/ultraplot/tests/baseline/test_three_axes.png deleted file mode 100644 index 99d9ef383..000000000 Binary files a/ultraplot/tests/baseline/test_three_axes.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_tick_direction.png b/ultraplot/tests/baseline/test_tick_direction.png deleted file mode 100644 index 530ddd0db..000000000 Binary files a/ultraplot/tests/baseline/test_tick_direction.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_tick_labels.png b/ultraplot/tests/baseline/test_tick_labels.png deleted file mode 100644 index 301e9dc3d..000000000 Binary files a/ultraplot/tests/baseline/test_tick_labels.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_tick_length.png b/ultraplot/tests/baseline/test_tick_length.png deleted file mode 100644 index 5082cc33b..000000000 Binary files a/ultraplot/tests/baseline/test_tick_length.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_tick_width.png b/ultraplot/tests/baseline/test_tick_width.png deleted file mode 100644 index d78ae24da..000000000 Binary files a/ultraplot/tests/baseline/test_tick_width.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_title_deflection.png b/ultraplot/tests/baseline/test_title_deflection.png deleted file mode 100644 index ef93e4f10..000000000 Binary files a/ultraplot/tests/baseline/test_title_deflection.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_triangular_functions.png b/ultraplot/tests/baseline/test_triangular_functions.png deleted file mode 100644 index e4e72f97d..000000000 Binary files a/ultraplot/tests/baseline/test_triangular_functions.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_tuple_handles.png b/ultraplot/tests/baseline/test_tuple_handles.png deleted file mode 100644 index f06422d27..000000000 Binary files a/ultraplot/tests/baseline/test_tuple_handles.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_twin_axes_1.png b/ultraplot/tests/baseline/test_twin_axes_1.png deleted file mode 100644 index 4bf783043..000000000 Binary files a/ultraplot/tests/baseline/test_twin_axes_1.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_twin_axes_2.png b/ultraplot/tests/baseline/test_twin_axes_2.png deleted file mode 100644 index 3ecbd0758..000000000 Binary files a/ultraplot/tests/baseline/test_twin_axes_2.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_twin_axes_3.png b/ultraplot/tests/baseline/test_twin_axes_3.png deleted file mode 100644 index de17748b4..000000000 Binary files a/ultraplot/tests/baseline/test_twin_axes_3.png and /dev/null differ diff --git a/ultraplot/tests/baseline/test_uneven_levels.png b/ultraplot/tests/baseline/test_uneven_levels.png deleted file mode 100644 index 7d5ef56ff..000000000 Binary files a/ultraplot/tests/baseline/test_uneven_levels.png and /dev/null differ diff --git a/ultraplot/tests/test_1dplots.py b/ultraplot/tests/test_1dplots.py index 338d631e2..3e55031e8 100644 --- a/ultraplot/tests/test_1dplots.py +++ b/ultraplot/tests/test_1dplots.py @@ -222,11 +222,9 @@ def test_pie_charts(): labels = ["foo", "bar", "baz", "biff", "buzz"] array = np.arange(1, 6) data = pd.Series(array, index=labels) - fig = uplt.figure() - ax = fig.subplot(121) - ax.pie(array, edgefix=True, labels=labels, ec="k", cycle="reds") - ax = fig.subplot(122) - ax.pie(data, ec="k", cycle="blues") + fig, ax = uplt.subplots(ncols=2) + ax[0].pie(array, edgefix=True, labels=labels, ec="k", cycle="reds") + ax[1].pie(data, ec="k", cycle="blues") return fig @@ -239,7 +237,11 @@ def test_parametric_labels(): uplt.rc.inlinefmt = "svg" fig, ax = uplt.subplots() ax.parametric( - state.rand(5), c=list("abcde"), lw=20, colorbar="b", cmap_kw={"left": 0.2} + state.rand(5), + c=list("abcde"), + lw=20, + colorbar="b", + cmap_kw={"left": 0.2}, ) return fig @@ -328,7 +330,10 @@ def test_scatter_cycle(): """ fig, ax = uplt.subplots() cycle = uplt.Cycle( - "538", marker=["X", "o", "s", "d"], sizes=[20, 100], edgecolors=["r", "k"] + "538", + marker=["X", "o", "s", "d"], + sizes=[20, 100], + edgecolors=["r", "k"], ) ax.scatter( state.rand(10, 4), diff --git a/ultraplot/tests/test_constructor.py b/ultraplot/tests/test_constructor.py new file mode 100644 index 000000000..942e5a05e --- /dev/null +++ b/ultraplot/tests/test_constructor.py @@ -0,0 +1,99 @@ +import ultraplot as uplt, pytest + + +def test_cycler(): + """ + Matplotlib uses different keywords to define properties. We must map UltraPlot's keywords to Matplotlib's keywords. We do this by constructing a new cycler object that ensures hat these mapping are done correctly. + """ + # Check if the cycling is working properly + # Take an arbitrary cycle object and cycle through all objects check if the cycle returns back to the first object + cycle = uplt.Cycle( + ["red", "green", "black"], + marker=["X", "o"], + sizes=[20, 100], + edgecolors=["r", "k"], + ) + first = cycle.get_next() + # first color, marker and size + assert first == { + "color": "red", + "marker": "X", + "markeredgecolor": "r", + "markersize": 20, + } + # We have 3 x 2 x 2 = 6 properties to cycle through + for idx in range(6): + last = cycle.get_next() + if idx < 5: + assert last != first + else: + assert last == first + + +def test_empty_cycle(): + """Tests default return + The default cycler always set black as a color + """ + cycle = uplt.Cycle() + props = cycle.get_next() + assert props == dict(color="black") + assert len(props) == 1 + + +def test_cycler_factory(): + """Test the factory function that creates cycler objects""" + # Test basic factory creation + cycler = uplt.Cycle(colors=["red", "blue"]) + assert isinstance(cycler, uplt.Cycle) + + +def test_matplotlib_keyword_mapping(): + """Test that UltraPlot keywords correctly map to Matplotlib keywords""" + cycle = uplt.Cycle(["red"], linestyle=["-"]) + props = cycle.get_next() + # Verify matplotlib-specific keywords + assert "color" in props + assert "linestyle" in props + + +def test_not_allowed_keyword(): + """Should raise error when we set a property that cannot be set""" + with pytest.raises(TypeError): + uplt.Cycle([], random_property1=["should not be allowed"]) + + +def test_cycler_edge_cases(): + """Test edge cases and error conditions""" + # Test with empty lists + cycle = uplt.Cycle(colors=[]) + assert cycle.get_next() == dict(color="black") # default fallback + + # Test with mismatched lengths + cycle = uplt.Cycle(["red", "blue"], marker=["o"]) + # Verify cycling still works with mismatched lengths + props1 = cycle.get_next() + props2 = cycle.get_next() + assert props1["marker"] == props2["marker"] # marker should stay same + assert props1["color"] != props2["color"] # color should cycle + + +# see https://github.com/matplotlib/matplotlib/pull/29469 +@pytest.mark.skip("Manual cyling not implemented yet in mpl") +def test_manual_cycle(): + cycle = uplt.Cycle( + ["red", "green", "black"], + marker=["X", "o"], + sizes=[20, 100], + edgecolors=["r", "k"], + ) + fig, ax = uplt.subplots() + ax.set_prop_cycle(cycle) + ax.scatter([1], [1]) + + ax = ax[0] # force to get single axis rather than GridSpec + parser = ax._get_lines + current_pos = parser._idx + cycled_pos = (current_pos + 1) % len(parser._cycler_items) + props = ax._active_cycle.get_next() + assert cycled_pos == parser._idx + assert props == parser._cycler_items[parser._idx]