From 612135facbee0d8a23e4911f91e5186c14bdf71d Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Sun, 2 Feb 2025 14:17:33 +0100 Subject: [PATCH 1/2] stashing --- ultraplot/axes/base.py | 2 +- ultraplot/axes/cartesian.py | 4 ++-- ultraplot/axes/plot.py | 17 ++++++++++++++--- ultraplot/config.py | 14 +++++++------- ultraplot/figure.py | 9 ++------- ultraplot/internals/__init__.py | 2 +- ultraplot/internals/warnings.py | 4 ++-- ultraplot/tests/test_1dplots.py | 11 ++++++----- ultraplot/tests/test_2dplots.py | 2 +- ultraplot/tests/test_legend.py | 2 +- 10 files changed, 37 insertions(+), 30 deletions(-) diff --git a/ultraplot/axes/base.py b/ultraplot/axes/base.py index f84d602e..ad2526b5 100644 --- a/ultraplot/axes/base.py +++ b/ultraplot/axes/base.py @@ -3188,7 +3188,7 @@ def text( else: transform = self._get_transform(transform) with warnings.catch_warnings(): # ignore duplicates (internal issues?) - warnings.simplefilter("ignore", warnings.UltraplotWarning) + warnings.simplefilter("ignore", warnings.UltraPlotWarning) kwargs.update(_pop_props(kwargs, "text")) # Update the text object using a monkey patch diff --git a/ultraplot/axes/cartesian.py b/ultraplot/axes/cartesian.py index 2cf34bdc..3d314b5f 100644 --- a/ultraplot/axes/cartesian.py +++ b/ultraplot/axes/cartesian.py @@ -675,7 +675,7 @@ def _update_formatter( # See: https://matplotlib.org/api/units_api.html # And: https://matplotlib.org/api/dates_api.html axis = getattr(self, f"{s}axis") - date = isinstance(axis.converter, DATE_CONVERTERS) + date = isinstance(axis.get_converter(), DATE_CONVERTERS) # Major formatter # NOTE: The default axis formatter accepts lots of keywords. So unlike @@ -814,7 +814,7 @@ def _update_rotation(self, s, *, rotation=None): setattr(self, default, False) elif not getattr(self, default): return # do not rotate - elif s == "x" and isinstance(axis.converter, DATE_CONVERTERS): + elif s == "x" and isinstance(axis.get_converter(), DATE_CONVERTERS): rotation = rc["formatter.timerotation"] else: rotation = "horizontal" diff --git a/ultraplot/axes/plot.py b/ultraplot/axes/plot.py index e1e83d3c..979591d6 100644 --- a/ultraplot/axes/plot.py +++ b/ultraplot/axes/plot.py @@ -2485,6 +2485,8 @@ def _parse_cycle( resolved_cycle = None case str() | int(): resolved_cycle = constructor.Cycle(cycle, **cycle_kw) + case constructor.Cycle(): + resolved_cycle = cycle case _: resolved_cycle = None @@ -3740,7 +3742,7 @@ def pie(self, x, explode, *, labelpad=None, labeldistance=None, **kwargs): ) kw = self._parse_cycle(x.size, **kw) objs = self._call_native( - "pie", x, explode, labeldistance=pad, wedgeprops=wedge_kw, **kw + "pie", x, explode = explode, labeldistance=pad, wedgeprops=wedge_kw, **kw ) objs = tuple(cbook.silent_list(type(seq[0]).__name__, seq) for seq in objs) self._fix_patch_edges(objs[0], **edgefix_kw, **wedge_kw) @@ -3828,6 +3830,7 @@ def _apply_boxplot( x, y, autoy=False, autoguide=False, vert=vert, **kw ) kw = self._parse_cycle(x.size, **kw) # possibly apply cycle + print(kw) if fill and fillcolor is None: parser = self._get_patches_for_fill fillcolor = [parser.get_next_color() for _ in range(x.size)] @@ -3844,7 +3847,14 @@ def _apply_boxplot( if hatch is None: hatch = [None for _ in range(x.size)] - artists = self._call_native("boxplot", y, vert=vert, **kw) + orientation = "vertical" if vert else "horizontal" + + # Mpl>=3.10 renames labels to tick_labels + # _parse_1d_args will generate the 'labels' key, we remap it here as other functions still rely on the 'labels' + tick_labels = kw.pop("labels", None) + if tick_labels is not None: + kw["tick_labels"] = tick_labels + artists = self._call_native("boxplot", y, orientation=orientation, **kw) artists = artists or {} # necessary? artists = { key: cbook.silent_list(type(objs[0]).__name__, objs) if objs else objs @@ -3992,10 +4002,11 @@ def _apply_violinplot( elif len(hatches) != len(y): raise ValueError(f"Retrieved {len(hatches)} hatches but need {len(y)}") + orientation = "vertical" if vert else "horizontal" artists = self._call_native( "violinplot", y, - vert=vert, + orientation=orientation, showmeans=False, showmedians=False, showextrema=False, diff --git a/ultraplot/config.py b/ultraplot/config.py index 7dc1b711..40f89937 100644 --- a/ultraplot/config.py +++ b/ultraplot/config.py @@ -952,7 +952,7 @@ def _get_item_dicts(self, key, value, skip_cycle=False): kw_matplotlib = {} # builtin properties with warnings.catch_warnings(): warnings.simplefilter("ignore", mpl.MatplotlibDeprecationWarning) - warnings.simplefilter("ignore", warnings.UltraplotWarning) + warnings.simplefilter("ignore", warnings.UltraPlotWarning) for key in keys: if key in rc_matplotlib: kw_matplotlib[key] = value @@ -1617,28 +1617,28 @@ def _load_file(self, path): added.add(key) # Get child dictionaries. Careful to have informative messages with warnings.catch_warnings(): - warnings.simplefilter("error", warnings.UltraplotWarning) + warnings.simplefilter("error", warnings.UltraPlotWarning) try: key, value = self._validate_key(key, value) value = self._validate_value(key, value) except KeyError: - warnings.simplefilter("default", warnings.UltraplotWarning) + warnings.simplefilter("default", warnings.UltraPlotWarning) warnings._warn_ultraplot( f"Invalid rc key {key!r} on {message}." ) continue except ValueError as err: - warnings.simplefilter("default", warnings.UltraplotWarning) + warnings.simplefilter("default", warnings.UltraPlotWarning) warnings._warn_ultraplot( f"Invalid rc value {value!r} for key {key!r} on {message}: {err}" ) # noqa: E501 continue - except warnings.UltraplotWarning as err: - warnings.simplefilter("default", warnings.UltraplotWarning) + except warnings.UltraPlotWarning as err: + warnings.simplefilter("default", warnings.UltraPlotWarning) warnings._warn_ultraplot( f"Outdated rc key {key!r} on {message}: {err}" ) # noqa: E501 - warnings.simplefilter("ignore", warnings.UltraplotWarning) + warnings.simplefilter("ignore", warnings.UltraPlotWarning) key, value = self._validate_key(key, value) value = self._validate_value(key, value) # Update the settings diff --git a/ultraplot/figure.py b/ultraplot/figure.py index 2796456e..77e65559 100644 --- a/ultraplot/figure.py +++ b/ultraplot/figure.py @@ -816,14 +816,9 @@ def _context_authorized(self): @staticmethod def _parse_backend(backend=None, basemap=None): """ - Handle deprication of basemap and cartopy package. + Handle potential deprication of basemap and cartopy package. """ - if basemap is not None: - backend = ("cartopy", "basemap")[bool(basemap)] - warnings._warn_ultraplot( - f"The 'basemap' keyword was deprecated in version 0.10.0 and will be " - f"removed in a future release. Please use backend={backend!r} instead." - ) + # Basemap is currently being developed again so are removing the deprecation warning return backend def _parse_proj( diff --git a/ultraplot/internals/__init__.py b/ultraplot/internals/__init__.py index 76b504c9..7a7ea938 100644 --- a/ultraplot/internals/__init__.py +++ b/ultraplot/internals/__init__.py @@ -59,7 +59,7 @@ def _not_none(*args, default=None, **kwargs): warnings, ) from .versions import _version_mpl, _version_cartopy # noqa: F401 -from .warnings import UltraplotWarning # noqa: F401 +from .warnings import UltraPlotWarning # noqa: F401 # Style aliases. We use this rather than matplotlib's normalize_kwargs and _alias_maps. diff --git a/ultraplot/internals/warnings.py b/ultraplot/internals/warnings.py index c4a2c338..f1bb8fb5 100644 --- a/ultraplot/internals/warnings.py +++ b/ultraplot/internals/warnings.py @@ -13,7 +13,7 @@ REGEX_INTERNAL = re.compile(r"\A(matplotlib|mpl_toolkits|ultraplot)\.") # Trivial warning class meant only to communicate the source of the warning -UltraplotWarning = type("UltraPlotWarning", (UserWarning,), {}) +UltraPlotWarning = type("UltraPlotWarning", (UserWarning,), {}) # Add due to overwriting the module name catch_warnings = warnings.catch_warnings @@ -50,7 +50,7 @@ def _warn_ultraplot(message): break # this is the first external frame frame = frame.f_back stacklevel += 1 - warnings.warn(message, UltraplotWarning, stacklevel=stacklevel) + warnings.warn(message, UltraPlotWarning, stacklevel=stacklevel) def _rename_objs(version, **kwargs): diff --git a/ultraplot/tests/test_1dplots.py b/ultraplot/tests/test_1dplots.py index a483c919..bdbe93e8 100644 --- a/ultraplot/tests/test_1dplots.py +++ b/ultraplot/tests/test_1dplots.py @@ -119,11 +119,11 @@ def test_boxplot_colors(): ax = fig.subplot(221) box_data = state.uniform(-3, 3, size=(1000, 5)) violin_data = state.normal(0, 1, size=(1000, 5)) - ax.box(box_data, fillcolor=["red", "blue", "green", "orange", "yellow"]) + ax.box(box_data, cycle=["red", "blue", "green", "orange", "yellow"]) ax = fig.subplot(222) ax.violin( violin_data, - fillcolor=["gray1", "gray7"], + cycle=["gray1", "gray7"], hatches=[None, "//", None, None, "//"], means=True, barstds=2, @@ -150,14 +150,15 @@ def test_boxplot_vectors(): datas = np.array(datas, dtype=object) assert len(datas) == len(coords) fig, ax = uplt.subplot(refwidth=3) + cycle = uplt.Cycle("538") ax.boxplot( coords, datas, lw=2, notch=False, whis=(10, 90), - cycle="538", fillalpha=[0.5, 0.5, 1], + cycle=cycle, hatch=[None, "//", "**"], boxlw=[2, 1, 1], ) @@ -218,7 +219,7 @@ def test_pie_charts(): """ Test basic pie plots. No examples in user guide right now. """ - uplt.rc.inlinefmt = "svg" + uplt.rc.inlineformat = "svg" labels = ["foo", "bar", "baz", "biff", "buzz"] array = np.arange(1, 6) data = pd.Series(array, index=labels) @@ -285,7 +286,7 @@ def test_scatter_args(): ax = axs[1] ax.scatter(data, c=data, cmap="reds") # column iteration ax = axs[2] - with pytest.warns(uplt.internals.UltraplotWarning) as record: + with pytest.warns(uplt.internals.UltraPlotWarning) as record: ax.scatter(data[:, 0], c=data, cmap="reds") # actual colors assert len(record) == 1 ax = axs[3] diff --git a/ultraplot/tests/test_2dplots.py b/ultraplot/tests/test_2dplots.py index 823484d2..d909b9ed 100644 --- a/ultraplot/tests/test_2dplots.py +++ b/ultraplot/tests/test_2dplots.py @@ -237,7 +237,7 @@ def test_ignore_message(): """ Test various ignored argument warnings. """ - warning = uplt.internals.UltraplotWarning + warning = uplt.internals.UltraPlotWarning fig, axs = uplt.subplots(ncols=2, nrows=2) with pytest.warns(warning): axs[0].contour(state.rand(5, 5) * 10, levels=uplt.arange(10), symmetric=True) diff --git a/ultraplot/tests/test_legend.py b/ultraplot/tests/test_legend.py index e91f93b7..6defa00a 100644 --- a/ultraplot/tests/test_legend.py +++ b/ultraplot/tests/test_legend.py @@ -119,7 +119,7 @@ def test_histogram_legend(): """ Support complex histogram legends. """ - uplt.rc.inlinefmt = "svg" + uplt.rc.inlineformat = "svg" fig, ax = uplt.subplots() res = ax.hist( state.rand(500, 2), 4, labels=("label", "other"), edgefix=True, legend="b" From 9a15aa0d2ef218936c92ab3fcff11f0bc64ad8e5 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Mon, 3 Feb 2025 05:24:42 +0100 Subject: [PATCH 2/2] several fixes --- ultraplot/tests/test_1dplots.py | 2 +- ultraplot/tests/test_2dplots.py | 8 ++++--- ultraplot/tests/test_axes.py | 1 + ultraplot/tests/test_format.py | 35 ++++++++++++++++------------- ultraplot/tests/test_integration.py | 4 +++- ultraplot/tests/test_subplots.py | 2 +- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/ultraplot/tests/test_1dplots.py b/ultraplot/tests/test_1dplots.py index bdbe93e8..22f69a08 100644 --- a/ultraplot/tests/test_1dplots.py +++ b/ultraplot/tests/test_1dplots.py @@ -235,7 +235,7 @@ def test_parametric_labels(): Test passing strings as parametric 'color values'. This is likely a common use case. """ - uplt.rc.inlinefmt = "svg" + uplt.rc.inlineformat = "svg" fig, ax = uplt.subplots() ax.parametric( state.rand(5), diff --git a/ultraplot/tests/test_2dplots.py b/ultraplot/tests/test_2dplots.py index d909b9ed..2f3a37f2 100644 --- a/ultraplot/tests/test_2dplots.py +++ b/ultraplot/tests/test_2dplots.py @@ -94,9 +94,11 @@ def test_colormap_mode(): Test auto extending, auto discrete. Should issue warnings. """ fig, axs = uplt.subplots(ncols=2, nrows=2, share=False) - axs[0].pcolor(state.rand(5, 5) % 0.3, extend="both", cyclic=True, colorbar="b") - axs[1].pcolor(state.rand(5, 5), sequential=True, diverging=True, colorbar="b") - axs[2].pcolor(state.rand(5, 5), discrete=False, qualitative=True, colorbar="b") + axs[0].pcolor(state.rand(5, 5) % 0.3, extend="neither", cyclic=True, colorbar="b") + with pytest.warns(uplt.warnings.UltraPlotWarning): + axs[1].pcolor(state.rand(5, 5), sequential=True, diverging=True, colorbar="b") + with pytest.warns(uplt.warnings.UltraPlotWarning): + axs[2].pcolor(state.rand(5, 5), discrete=False, qualitative=True, colorbar="b") uplt.rc["cmap.discrete"] = False # should be ignored below axs[3].contourf(state.rand(5, 5), colorbar="b") return fig diff --git a/ultraplot/tests/test_axes.py b/ultraplot/tests/test_axes.py index f73bad44..778ba58e 100644 --- a/ultraplot/tests/test_axes.py +++ b/ultraplot/tests/test_axes.py @@ -111,6 +111,7 @@ def test_panels_suplabels_three_hor_panels(): return fig +@pytest.mark.mpl_image_compare def test_panels_suplabels_three_hor_panels_donotinlcude(): """ Test label sharing for `includepanels=True`. diff --git a/ultraplot/tests/test_format.py b/ultraplot/tests/test_format.py index 9d8be905..1d3d7177 100644 --- a/ultraplot/tests/test_format.py +++ b/ultraplot/tests/test_format.py @@ -84,22 +84,25 @@ def test_multi_formatting(): """ fig, axs = uplt.subplots(ncols=2, proj=("cart", "cyl")) axs[0].pcolormesh(state.rand(5, 5)) - fig.format( - land=1, - labels=1, - lonlim=(0, 90), - latlim=(0, 90), - xlim=(0, 10), - ylim=(0, 10), - ) - axs[:1].format( - land=1, - labels=1, - lonlim=(0, 90), - latlim=(0, 90), - xlim=(0, 10), - ylim=(0, 10), - ) + + # Warning is raied based on projection. Cart does not have lonlim, latllim or labels + with pytest.warns(uplt.warnings.UltraPlotWarning): + axs[:1].format( + land=1, + labels=1, + lonlim=(0, 90), + latlim=(0, 90), + xlim=(0, 10), + ylim=(0, 10), + ) + fig.format( + land=1, + labels=1, + lonlim=(0, 90), + latlim=(0, 90), + xlim=(0, 10), + ylim=(0, 10), + ) return fig diff --git a/ultraplot/tests/test_integration.py b/ultraplot/tests/test_integration.py index 9d63e0e7..0d50e529 100644 --- a/ultraplot/tests/test_integration.py +++ b/ultraplot/tests/test_integration.py @@ -87,7 +87,9 @@ def test_seaborn_swarmplot(): tips = sns.load_dataset("tips") fig = uplt.figure(refwidth=3) ax = fig.subplot() - sns.swarmplot(ax=ax, x="day", y="total_bill", data=tips, palette="cubehelix") + sns.swarmplot( + ax=ax, x="day", hue="day", y="total_bill", data=tips, palette="cubehelix" + ) # fig, ax = uplt.subplots() # sns.swarmplot(y=state.normal(size=100), ax=ax) return fig diff --git a/ultraplot/tests/test_subplots.py b/ultraplot/tests/test_subplots.py index 797068d3..12659248 100644 --- a/ultraplot/tests/test_subplots.py +++ b/ultraplot/tests/test_subplots.py @@ -113,7 +113,6 @@ def test_gridspec_copies(): """ fig1, ax = uplt.subplots(ncols=2) gs = fig1.gridspec.copy(left=5, wspace=0, right=5) - return fig1 fig2 = uplt.figure() fig2.add_subplots(gs) fig = uplt.figure() @@ -142,6 +141,7 @@ def test_aligned_outer_guides(): return fig +@pytest.mark.mpl_image_compare def test_reference_aspect(): """ Rigorous test of reference aspect ratio accuracy.