Add gridded heatmap guidance to VegaLiteAgent prompt#1824
Closed
ghostiee-11 wants to merge 9 commits into
Closed
Conversation
After holoviz#1791 landed, loading a NetCDF file and asking the AI to plot it produces a scatter or line chart rather than a 2D heatmap, because: - hvPlotBaseView had no way to pass a value column (C) to hvplot - The AI agents had no awareness the pipeline was backed by gridded xarray data Changes: - Add `C` param (value column) to hvPlotBaseView; wire into df.hvplot() - Add `quadmesh` to the kind selector - New lumen/ai/gridded.py: detect_gridded() returns coordinate/variable metadata when pipeline.source is XArraySQLSource, else None - BaseViewAgent._generate_yaml_spec: call detect_gridded() once, pass result as `gridded` template variable - BaseViewAgent/main.jinja2 + hvPlotAgent/main.jinja2: conditional block guides LLM to use kind='heatmap' with x/y/C for gridded data - hvPlotAgent._extract_spec: drop by/groupby when kind=heatmap Addresses holoviz#1821 (1/3)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1824 +/- ##
==========================================
+ Coverage 70.02% 70.24% +0.21%
==========================================
Files 193 196 +3
Lines 32445 32808 +363
==========================================
+ Hits 22721 23045 +324
- Misses 9724 9763 +39 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
philippjfr
reviewed
Apr 21, 2026
| if self.streaming: | ||
| processed['stream'] = self._data_stream | ||
| if self.C is not None: | ||
| processed['C'] = self.C |
Member
There was a problem hiding this comment.
hvPlot generally uses z, only heatmap support C.
Collaborator
Author
There was a problem hiding this comment.
Sure thanks will change to use z
ghostiee-11
added a commit
to ghostiee-11/lumen
that referenced
this pull request
Apr 21, 2026
Per review on holoviz#1824: hvPlot uses `C` only for heatmap (matplotlib hexbin convention), and `z` for image, quadmesh, contourf. Exposing the param as `C` for all gridded kinds would silently pass C= to plot kinds that expect z=. Fix: rename the public param `C` to `z` and map internally to C= only when kind='heatmap', otherwise pass through as z=. Updated prompt guidance in BaseViewAgent/main.jinja2 and hvPlotAgent/main.jinja2 to use z= and mention the other gridded kinds. Tests updated to use z= and a new test verifies the z-to-C mapping is conditional on kind.
Per review on holoviz#1824: hvPlot uses `C` only for heatmap (matplotlib hexbin convention), and `z` for image, quadmesh, contourf. Exposing the param as `C` for all gridded kinds would silently pass C= to plot kinds that expect z=. Fix: rename the public param `C` to `z` and map internally to C= only when kind='heatmap', otherwise pass through as z=. Updated prompt guidance in BaseViewAgent/main.jinja2 and hvPlotAgent/main.jinja2 to use z= and mention the other gridded kinds. Tests updated to use z= and a new test verifies the z-to-C mapping is conditional on kind.
ghostiee-11
force-pushed
the
feat/xarray-gridded-vegalite
branch
from
April 21, 2026 14:49
747554b to
d0bdaa0
Compare
ahuang11
reviewed
Apr 22, 2026
| Data originates from an xarray dataset. | ||
| - dimensions: {{ gridded.dims | join(', ') }} | ||
| - data variables: {{ gridded.data_vars | join(', ') }} | ||
| Use kind='heatmap' (or 'quadmesh'/'image'/'contourf') with x/y set to coordinate dimensions and z set to the value column. |
Contributor
There was a problem hiding this comment.
This isn't a valid kind across VegaLiteView I think...
Per review on holoviz#1823: heatmap treats x/y as ordinal categories, which is semantically wrong for continuous-coordinate gridded data. quadmesh and image preserve the continuous axes and are the right default for xarray- derived grids. But hvPlot's quadmesh/image/contourf kinds raise NotImplementedError on long-form pandas DataFrames (they expect a 2D array or xarray), and XArraySQLSource returns pandas via SQL. Fix: hvPlotBaseView.get_plot now pivots the long-form DataFrame to a 2D xarray DataArray (via set_index([y, x])[z].to_xarray()) when kind is in _GRIDDED_KINDS = (quadmesh, image, contourf) and x/y/z are set. Safety guards in _to_gridded: - Skips pivot if the input is not a pandas DataFrame (xarray objects pass through unchanged, so future xarray-returning sources work). - Skips pivot if hvplot.xarray failed to import (import flag set at __init__ time; avoids AttributeError at plot time). - Skips pivot if x/y/z are missing or required columns are absent (falls back to hvPlot's own NotImplementedError). - Skips pivot if duplicate (y, x) pairs exist (pivot would be ambiguous). - Raises ValueError if the pivoted grid would exceed _GRIDDED_MAX_CELLS = 10M cells (~80MB for float64) to prevent OOM. Prompt guidance updated: recommends kind='quadmesh' as the primary choice for xarray-derived gridded data, with image/contourf as alternatives and heatmap as a fallback for ordinal/categorical axes. heatmap still stays on the pandas path (it works fine there). hvplot.xarray is imported in hvPlotBaseView.__init__ alongside hvplot.pandas so the .hvplot accessor is available on DataArray. Tests (10 in test_hvplot_gridded.py): - test_hvplot_quadmesh_from_longform_df: renders hv.QuadMesh - test_hvplot_image_from_longform_df: renders hv.Image - test_hvplot_gridded_size_guard_raises: ValueError over cap - test_hvplot_gridded_skips_pivot_if_xarray_unavailable: flag fallback - test_hvplot_gridded_passes_through_non_dataframe: xarray input skip - existing z-param and heatmap tests updated
Pre-commit ruff auto-fix flagged the # noqa as unused; the try/except already silences the ImportError, so the # type: ignore is enough.
The previous lint cleanup over-stripped the noqa on hvplot.dask, which is a genuine F401 (conditional side-effect import for the .hvplot accessor on dask DataFrames). Restored as scoped # noqa: F401 so RUF100 recognises it as a targeted suppression.
ghostiee-11
added a commit
to ghostiee-11/lumen
that referenced
this pull request
Apr 23, 2026
Two review responses bundled: 1. Per review on holoviz#1824: BaseViewAgent/main.jinja2 is the base template inherited by hvPlotAgent, VegaLiteAgent, and DeckGLAgent. The previous gridded block named kind='quadmesh'/'image'/'contourf'/'heatmap' which are hvPlot-only concepts. VegaLite uses mark: rect, DeckGL uses layer types, so injecting hvPlot kind values into their prompt context is misleading. Kept the metadata (xarray source, dims, data_vars) in the base block; each agent's own prompt carries the syntax-specific guidance. Updated test to assert no hvPlot kinds leak into the base. 2. Style cleanup for lint discipline: moved holoviews/pandas/xarray/ unittest.mock imports to the top of test_hvplot_gridded.py (was inline inside test bodies). Replaced two em dashes in hvPlotAgent prompt and test docstring.
ghostiee-11
force-pushed
the
feat/xarray-gridded-vegalite
branch
from
April 23, 2026 19:40
d0bdaa0 to
3bb8c6c
Compare
ghostiee-11
marked this pull request as draft
April 23, 2026 19:42
Two review responses bundled: 1. Per review on holoviz#1824: BaseViewAgent/main.jinja2 is the base template inherited by hvPlotAgent, VegaLiteAgent, and DeckGLAgent. The previous gridded block named kind='quadmesh'/'image'/'contourf'/'heatmap' which are hvPlot-only concepts. VegaLite uses mark: rect, DeckGL uses layer types, so injecting hvPlot kind values into their prompt context is misleading. Kept the metadata (xarray source, dims, data_vars) in the base block; each agent's own prompt carries the syntax-specific guidance. Updated test to assert no hvPlot kinds leak into the base. 2. Style cleanup for lint discipline: moved MagicMock/patch/holoviews/ numpy/pandas imports to the top of test_hvplot_gridded.py (was inline inside test bodies). xarray is an optional dep, so it is guarded with pytest.importorskip inside the tests that actually use it to keep test-core collection working. Replaced two em dashes in hvPlotAgent prompt and a test docstring.
ghostiee-11
force-pushed
the
feat/xarray-gridded-vegalite
branch
from
April 23, 2026 19:58
3bb8c6c to
a64310f
Compare
ghostiee-11
added a commit
to ghostiee-11/lumen
that referenced
this pull request
Apr 23, 2026
Two review responses bundled: 1. Per review on holoviz#1824: BaseViewAgent/main.jinja2 is the base template inherited by hvPlotAgent, VegaLiteAgent, and DeckGLAgent. The previous gridded block named kind='quadmesh'/'image'/'contourf'/'heatmap' which are hvPlot-only concepts. VegaLite uses mark: rect, DeckGL uses layer types, so injecting hvPlot kind values into their prompt context is misleading. Kept the metadata (xarray source, dims, data_vars) in the base block; each agent's own prompt carries the syntax-specific guidance. Updated test to assert no hvPlot kinds leak into the base. 2. Style cleanup for lint discipline: moved holoviews/pandas/xarray/ unittest.mock imports to the top of test_hvplot_gridded.py (was inline inside test bodies). Replaced two em dashes in hvPlotAgent prompt and test docstring.
ghostiee-11
marked this pull request as ready for review
April 23, 2026 20:10
Per review on holoviz#1823: detect_gridded is a small one-function helper; it does not warrant its own module. Moved into lumen/ai/utils.py alongside the other AI helpers and removed the standalone gridded.py. Updated imports in lumen/ai/agents/base_view.py and lumen/tests/ai/test_gridded.py.
ghostiee-11
force-pushed
the
feat/xarray-gridded-vegalite
branch
from
April 24, 2026 12:22
a64310f to
d70be68
Compare
ahuang11
marked this pull request as draft
May 6, 2026 21:51
Collaborator
Author
|
Folding this into #1823, which combines the hvPlot, VegaLite, and DeckGL gridded support into one PR. Closing to keep it in a single reviewable PR. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
When the AI receives a gridded xarray-derived dataset and the user asks for a visualisation, the VegaLite agent has no guidance on how to represent 2D fields. It falls back to geographic point charts (longitude/latitude encoding) which render empty for non-geographic grids, or picks an inappropriate mark type.
This adds a guarded block to the VegaLiteAgent prompt that fires only when the pipeline originates from an xarray source. It instructs the LLM to use
mark: rectwith ordinal x/y axes mapped to the coordinate dimensions and aviridis colour scale on the value column — the correct Vega-Lite pattern for a
2D heatmap from long-form data.
Demo
How to reproduce
mark: rectwith correct x, y, color mappingHow Has This Been Tested?
Addresses #1821 (2/3)