-
-
Notifications
You must be signed in to change notification settings - Fork 30
Support plotting xarray grids (hvPlot + VegaLite + DeckGL) #1823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ghostiee-11
wants to merge
29
commits into
holoviz:main
Choose a base branch
from
ghostiee-11:feat/xarray-gridded-hvplot
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 7 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
8d2f484
Add C param and gridded heatmap support for xarray-derived data
ghostiee-11 4cf3dd7
Fix isort import ordering
ghostiee-11 782bba8
review: rename C to z for gridded plot kinds
ghostiee-11 f6e188f
review: pivot long-form pandas to xarray for quadmesh/image/contourf
ghostiee-11 9dbe78a
chore: remove redundant # noqa on hvplot.xarray import
ghostiee-11 19057e5
chore: restore # noqa: F401 on hvplot.dask side-effect import
ghostiee-11 43e7574
review: keep BaseViewAgent prompt agent-agnostic, move imports to top
ghostiee-11 5939777
review: move detect_gridded into lumen.ai.utils
ghostiee-11 2f4df35
review: address reviewer feedback on gridded hvPlot support
ghostiee-11 d99b530
review: collapse _to_gridded guards and cover xarray Dataset path
ghostiee-11 c67845e
feat: add VegaLite gridded xarray heatmap support
ghostiee-11 a52c9cd
feat: add DeckGL gridded xarray support and row-count guard
ghostiee-11 78ff200
Merge remote-tracking branch 'origin/main' into feat/xarray-gridded-h…
ghostiee-11 81e3494
fix: CI
ghostiee-11 c6caf31
Merge origin/main into feat/xarray-gridded-hvplot
ghostiee-11 3f3e821
fix: keep groupby on hvplot heatmap specs
ghostiee-11 088df7d
fix: address review feedback on gridded views
ghostiee-11 a4b6cfb
fix: CI
ghostiee-11 3f5d491
fix: skip hvplot.xarray import on the blocked gridded path
ghostiee-11 2346cad
fix: address review feedback on gridded views
ghostiee-11 b562c22
feat: page extra groupby dimensions in gridded hvPlot pivot
ghostiee-11 bf3e14d
feat: cap hvPlot render size to protect the browser
ghostiee-11 f9b22a2
feat: render gridded xarray sources via xarray-sql to_dataset
ghostiee-11 3544efb
feat: subset gridded VegaLite/DeckGL views to a single 2D slice
ghostiee-11 e386bd8
fix: CI
ghostiee-11 64355da
refactor: drive the gridded 2D subset from the spec, not a lon/lat guess
ghostiee-11 81940f0
refactor: make the gridded subset explicit about the spec
ghostiee-11 63ad67f
feat: line/time-series for gridded xarray, rename to get_gridded_meta…
ghostiee-11 ed1c4b2
fix: conflicts
ghostiee-11 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import Any | ||
|
|
||
| from ..pipeline import Pipeline | ||
| from ..sources.xarray_sql import XArraySQLSource | ||
| from ..util import check_xarray_available | ||
|
|
||
|
|
||
| def detect_gridded(pipeline: Pipeline) -> dict[str, Any] | None: | ||
|
ghostiee-11 marked this conversation as resolved.
Outdated
|
||
| """Return gridded metadata if pipeline.source is an XArraySQLSource, else None. | ||
|
|
||
| Returns a dict with keys ``dims``, ``coords``, ``data_vars``, ``source_type``, | ||
| or ``None`` for tabular pipelines. | ||
| """ | ||
| source = pipeline.source | ||
| if not isinstance(source, XArraySQLSource): | ||
| return None | ||
| if not check_xarray_available(): | ||
| return None | ||
| ds = source.dataset | ||
| return { | ||
| 'source_type': 'xarray', | ||
| 'dims': list(ds.dims), | ||
| 'coords': {k: list(ds.coords[k].shape) for k in ds.coords}, | ||
| 'data_vars': list(ds.data_vars), | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| import datetime | ||
|
|
||
| import numpy as np | ||
| import pandas as pd | ||
| import pytest | ||
|
|
||
| xr = pytest.importorskip("xarray") | ||
| pytest.importorskip("xarray_sql") | ||
|
|
||
| from lumen.ai.config import PROMPTS_DIR | ||
| from lumen.ai.gridded import detect_gridded | ||
| from lumen.ai.utils import render_template | ||
| from lumen.pipeline import Pipeline | ||
| from lumen.sources.base import InMemorySource | ||
| from lumen.sources.xarray_sql import XArraySQLSource | ||
| from lumen.util import check_xarray_available | ||
|
|
||
| pytestmark = pytest.mark.skipif( | ||
| not check_xarray_available(), reason="xarray not installed" | ||
| ) | ||
|
|
||
|
|
||
| # ---- Fixtures ---- | ||
|
|
||
| @pytest.fixture | ||
| def simple_dataset(): | ||
| lats = np.array([0.0, 1.0, 2.0]) | ||
| lons = np.array([10.0, 20.0, 30.0, 40.0]) | ||
| air = np.arange(12, dtype=float).reshape(3, 4) | ||
| return xr.Dataset( | ||
| {"air": (["lat", "lon"], air)}, | ||
| coords={"lat": lats, "lon": lons}, | ||
| ) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def xarray_source(simple_dataset): | ||
| return XArraySQLSource(_dataset=simple_dataset) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def xarray_pipeline(xarray_source): | ||
| return Pipeline(source=xarray_source, table="air") | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def tabular_pipeline(): | ||
| df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}) | ||
| source = InMemorySource(tables={"data": df}) | ||
| return Pipeline(source=source, table="data") | ||
|
|
||
|
|
||
| # ---- detect_gridded tests ---- | ||
|
|
||
| def test_detect_gridded_xarray_source(xarray_pipeline): | ||
| result = detect_gridded(xarray_pipeline) | ||
| assert result is not None | ||
| assert result["source_type"] == "xarray" | ||
| assert "lat" in result["dims"] | ||
| assert "lon" in result["dims"] | ||
| assert "air" in result["data_vars"] | ||
|
|
||
|
|
||
| def test_detect_gridded_pandas_source(tabular_pipeline): | ||
| result = detect_gridded(tabular_pipeline) | ||
| assert result is None | ||
|
|
||
|
|
||
| # ---- Prompt rendering tests ---- | ||
|
|
||
| def _base_context(gridded=None): | ||
| """Minimal context required to render BaseViewAgent/main.jinja2.""" | ||
| class _FakeSource: | ||
| dialect = None | ||
|
|
||
| class _FakePipeline: | ||
| table = "air" | ||
| source = _FakeSource() | ||
|
|
||
| class _FakeMemory(dict): | ||
| pass | ||
|
|
||
| memory = _FakeMemory({ | ||
| "pipeline": _FakePipeline(), | ||
| "data": "lat,lon,air\n0,10,1.0", | ||
| }) | ||
| return dict( | ||
| memory=memory, | ||
| doc="hvPlotUIView description", | ||
| gridded=gridded, | ||
| current_datetime=datetime.datetime(2026, 1, 1), | ||
| actor_name="hvPlotAgent", | ||
| ) | ||
|
|
||
|
|
||
| def test_baseview_prompt_includes_gridded_block(): | ||
| gridded = { | ||
| "source_type": "xarray", | ||
| "dims": ["lat", "lon"], | ||
| "coords": {"lat": [3], "lon": [4]}, | ||
| "data_vars": ["air"], | ||
| } | ||
| rendered = render_template( | ||
| PROMPTS_DIR / "BaseViewAgent" / "main.jinja2", | ||
| **_base_context(gridded=gridded), | ||
| ) | ||
| assert "xarray dataset" in rendered | ||
| assert "lat, lon" in rendered | ||
| assert "air" in rendered | ||
| # The base prompt must stay agent-agnostic: no hvPlot-specific kind | ||
| # values, since VegaLite and DeckGL inherit this template too. | ||
| assert "kind=" not in rendered | ||
| assert "quadmesh" not in rendered | ||
| assert "heatmap" not in rendered | ||
|
|
||
|
|
||
| def test_baseview_prompt_no_gridded_block_for_tabular(): | ||
| rendered = render_template( | ||
| PROMPTS_DIR / "BaseViewAgent" / "main.jinja2", | ||
| **_base_context(gridded=None), | ||
| ) | ||
| assert "xarray dataset" not in rendered | ||
| assert "gridded plot kinds" not in rendered | ||
|
|
||
|
|
||
| def test_hvplot_prompt_includes_gridded_rules(): | ||
| gridded = { | ||
| "source_type": "xarray", | ||
| "dims": ["lat", "lon"], | ||
| "coords": {"lat": [3], "lon": [4]}, | ||
| "data_vars": ["air"], | ||
| } | ||
| rendered = render_template( | ||
| PROMPTS_DIR / "hvPlotAgent" / "main.jinja2", | ||
| **_base_context(gridded=gridded), | ||
| ) | ||
| assert "quadmesh" in rendered | ||
| assert "z" in rendered | ||
|
|
||
|
|
||
| def test_hvplot_prompt_no_gridded_rules_for_tabular(): | ||
| rendered = render_template( | ||
| PROMPTS_DIR / "hvPlotAgent" / "main.jinja2", | ||
| **_base_context(gridded=None), | ||
| ) | ||
| assert "For gridded xarray data" not in rendered |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Groupby I think is still valid for heatmap