Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2bdd15b
add seaborn context processing
cvanelteren Nov 12, 2025
5cae6f0
rm debug
cvanelteren Nov 12, 2025
0786d28
add unittest
cvanelteren Nov 12, 2025
61ae661
resolve iterable
cvanelteren Nov 12, 2025
6dab0f2
relax legend filter
cvanelteren Nov 12, 2025
2887b3f
add seaborn import
cvanelteren Nov 12, 2025
d542103
add more unittests
cvanelteren Nov 12, 2025
4f9c13b
add ctx texts
cvanelteren Nov 12, 2025
7ea041c
implement mark external and context managing
cvanelteren Nov 12, 2025
c12de2b
fix test
cvanelteren Nov 12, 2025
80fef46
refactor classes for clarity
cvanelteren Nov 12, 2025
7d93bb1
update tests
cvanelteren Nov 12, 2025
288e8bb
more fixes
cvanelteren Nov 12, 2025
8ecccdd
more tests
cvanelteren Nov 12, 2025
aaa1cbc
minor fix
cvanelteren Nov 12, 2025
219e611
minor fix
cvanelteren Nov 12, 2025
3b5c90d
fix for mpl 3.9
cvanelteren Nov 13, 2025
9435fda
remove stack frame
cvanelteren Nov 13, 2025
4c44e82
adjust and remove unecessary tests
cvanelteren Nov 13, 2025
c8635c8
more fixes
cvanelteren Nov 13, 2025
3f969bf
add external to pass test
cvanelteren Nov 13, 2025
1b1ddc4
restore test
cvanelteren Nov 16, 2025
82fbb5d
rm dup
cvanelteren Nov 16, 2025
d5b2aa9
finalize docstring
cvanelteren Nov 16, 2025
8d2824c
remove fallback
cvanelteren Nov 17, 2025
8ee3fe3
Merge branch 'main' into add-seaborn-ctx
cvanelteren Nov 18, 2025
e6ba821
Apply suggestion from @beckermr
beckermr Nov 18, 2025
5923cdb
Apply suggestion from @beckermr
beckermr Nov 18, 2025
5287cdb
fix bar and test
cvanelteren Nov 19, 2025
d5df6a2
Merge branch 'main' into add-seaborn-ctx
cvanelteren Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add more unittests
  • Loading branch information
cvanelteren committed Nov 12, 2025
commit d5421032afb23c8ea6987bd25d9bc1e032e3fb3b
69 changes: 66 additions & 3 deletions ultraplot/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,73 @@
"""
Test xarray, pandas, pint, seaborn integration.
"""
import numpy as np, pandas as pd, seaborn as sns
import xarray as xr
import ultraplot as uplt, pytest
import numpy as np
import pandas as pd
import pint
import pytest
import seaborn as sns
import xarray as xr

import ultraplot as uplt


def test_seaborn_helpers_filtered_from_legend():
"""
Seaborn-generated helper artists (e.g., CI bands) must be synthetic-tagged and
filtered out of legends so that only hue categories appear.
"""
fig, ax = uplt.subplots()

# Create simple dataset with two hue levels
df = pd.DataFrame(
{
"x": np.concatenate([np.arange(10)] * 2),
"y": np.concatenate([np.arange(10), np.arange(10) + 1]),
"hue": ["h1"] * 10 + ["h2"] * 10,
}
)

# Draw seaborn lineplot (which may create helper artists internally)
sns.lineplot(data=df, x="x", y="y", hue="hue", ax=ax)

# Explicitly create legend and verify labels
leg = ax.legend()
labels = {t.get_text() for t in leg.get_texts()}

# Only hue labels should be present
assert {"h1", "h2"}.issubset(labels)

# Spurious or synthetic labels must not appear
for bad in (
"y",
"ymin",
"ymax",
"_ultraplot_fill",
"_ultraplot_shade",
"_ultraplot_fade",
):
assert bad not in labels


def test_user_labeled_shading_appears_in_legend():
"""
User-labeled shading (fill_between) must appear in legend even after seaborn plotting.
"""
fig, ax = uplt.subplots()

# Seaborn plot first (to ensure seaborn context was present earlier)
df = pd.DataFrame({"x": np.arange(10), "y": np.arange(10)})
sns.lineplot(data=df, x="x", y="y", ax=ax, label="line")

# Add explicit user-labeled shading on the same axes
x = np.arange(10)
ax.fill_between(x, x - 0.2, x + 0.2, alpha=0.2, label="CI band")

# Legend must include both the seaborn line label and our shaded band label
leg = ax.legend()
labels = {t.get_text() for t in leg.get_texts()}
assert "line" in labels
assert "CI band" in labels


@pytest.mark.mpl_image_compare
Expand Down
59 changes: 59 additions & 0 deletions ultraplot/tests/test_legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,62 @@ def test_sync_label_dict(rng):
0
]._legend_dict, "Old legend not removed from dict"
uplt.close(fig)


def test_synthetic_handles_filtered():
"""
Synthetic-tagged helper artists must be ignored by legend parsing even when
explicitly passed as handles.
"""
fig, ax = uplt.subplots()
(h1,) = ax.plot([0, 1], label="visible")
(h2,) = ax.plot([1, 0], label="helper")
# Mark helper as synthetic; it should be filtered out from legend entries
setattr(h2, "_ultraplot_synthetic", True)

leg = ax.legend([h1, h2], loc="best")
labels = [t.get_text() for t in leg.get_texts()]
assert "visible" in labels
assert "helper" not in labels
uplt.close(fig)


def test_fill_between_included_in_legend():
"""
Legitimate fill_between/area handles must appear in legends (regression for
previously skipped FillBetweenPolyCollection).
"""
fig, ax = uplt.subplots()
x = np.arange(5)
y1 = np.zeros(5)
y2 = np.ones(5)
ax.fill_between(x, y1, y2, label="band")

leg = ax.legend(loc="best")
labels = [t.get_text() for t in leg.get_texts()]
assert "band" in labels
uplt.close(fig)


def test_seaborn_defers_on_the_fly_legend(monkeypatch):
"""
When detected inside a seaborn call, on-the-fly legend creation is deferred
(no legend is created until explicitly requested).
"""
fig, ax = uplt.subplots()

# Force seaborn context detection to True
import ultraplot.axes.base as base_mod

monkeypatch.setattr(base_mod, "_inside_seaborn_call", lambda: True)
ax.plot([0, 1], label="a", legend="b")

# No legend should have been created yet
assert getattr(ax[0], "legend_", None) is None

# Now allow legend creation and explicitly request it
monkeypatch.setattr(base_mod, "_inside_seaborn_call", lambda: False)
leg = ax.legend(loc="b")
labels = [t.get_text() for t in leg.get_texts()]
assert "a" in labels
uplt.close(fig)