A newer version of the Gradio SDK is available:
6.5.1
SPECS.md — Panoply-Lite (Python/Gradio)
Goal: A browser-based viewer for netCDF/HDF/GRIB/Zarr datasets with an xarray+Dask backend, Cartopy maps, multi-dimensional slicing, animations, custom color tables (CPT/ACT/RGB), map projections, OPeNDAP/THREDDS/S3/Zarr support, and exports (PNG/SVG/PDF/MP4). Think “Panoply in the browser.”
0) TL;DR Build Contract
- Deliverable:
app.py+panlite/package + tests + pinnedpyproject.toml(orrequirements.txt) + minimal sample assets. - Runtime: Python 3.11; CPU-only acceptable; FFmpeg required for MP4.
- UI: Gradio Blocks (single page).
- Perf: Lazy I/O with Dask; responsive for slices ≤ ~5e6 elements.
- Outcomes (Definition of Done): Load ERA5/CMIP-like datasets; produce a global map, a time–latitude section, a 1D line plot, an animation (MP4), and an A–B difference contour; export PNG/SVG/PDF; save/load view state JSON.
1) Scope
1.1 MVP Features
- Open sources: local files;
https://(incl. OPeNDAP/THREDDS);s3://(anonymous or creds);zarr://(local/remote). - Formats/engines:
- netCDF/HDF5 →
xarray.open_dataset(..., engine="h5netcdf" | "netcdf4") - GRIB →
cfgrib(requires ecCodes) - Zarr →
xarray.open_zarr(...)
- netCDF/HDF5 →
- Discovery: list variables, dims, shapes, dtypes, attrs; CF axis inference (lat, lon, time, level).
- Slicing: choose X/Y axes; set index/value selectors for remaining dims (nearest when numeric); time selectors.
- Plots:
- 1D: line (any single dim)
- 2D: image/contour (any two dims)
- Map: lon–lat georeferenced 2D with Cartopy (projections, coastlines, gridlines)
- Sections: time–lat, time–lev, lon–lev (pick dims)
- Combine: sum/avg/diff of two variables on a common grid (with reindex/broadcast; error out if CRS differs).
- Colors: matplotlib colormaps + load CPT/ACT/RGB tables.
- Overlays: coastlines, borders; optional land/ocean masks.
- Export: PNG/SVG/PDF; MP4 (or frames) for animations.
- State: save/load a JSON “view state.”
1.2 v1.1 Stretch (optional)
- KMZ export (ground overlay tiles).
- GeoTIFF export for georeferenced 2D arrays.
- Trajectory plots (CF trajectories).
- Zonal mean helper (lat/lon aggregation).
- xESMF regridding for combine.
1.3 Non-Goals (v1)
3D volume rendering; advanced reprojection pipelines; interactive WebGL.
2) Architecture & Layout
panoply-lite/ app.py panlite/ init.py io.py # open/close; engine select; cache; variable listing grid.py # alignment, simple reindex/broadcast; combine ops; sections plot.py # 1D/2D/map plotting; exports anim.py # animate over a dim -> MP4/frames colors.py # CPT/ACT/RGB loaders -> matplotlib Colormap state.py # view-state (serialize/deserialize; schema validate) utils.py # CF axis guess; CRS helpers; small helpers assets/ colormaps/ # sample .cpt/.act/.rgb tests/ test_io.py test_plot.py test_anim.py data/ # tiny sample datasets (≤5 MB) pyproject.toml (or requirements.txt) README.md SPECS.md
3) Dependencies (pin reasonably)
- Core: xarray, dask[complete], numpy, pandas, fsspec, s3fs, zarr, h5netcdf, cfgrib, eccodes
- Geo: cartopy, pyproj, rioxarray
- Viz: matplotlib
- Web UI: gradio>=4
- Misc: pydantic, orjson, pytest, ruff
- System: ffmpeg in PATH for MP4
requirements.txt example:
xarray dask[complete] fsspec s3fs zarr h5netcdf cfgrib eccodes rioxarray cartopy pyproj matplotlib gradio>=4 numpy pandas pydantic orjson pytest
4) API Surface
io.py
- open_any(uri, engine=None, chunks="auto") -> DatasetHandle
- list_variables(handle) -> list[VariableSpec]
- get_dataarray(handle, var) -> xr.DataArray
- close(handle)
grid.py
- align_for_combine(a, b, method="reindex")
- combine(a, b, op="sum"|"avg"|"diff")
- section(da, along: str, fixed: dict)
plot.py
- plot_1d(da, **style) -> Figure
- plot_2d(da, kind="image"|"contour", **style) -> Figure
- plot_map(da, proj, **style) -> Figure
- export_fig(fig, fmt="png"|"svg"|"pdf", dpi=150, out_path=None)
anim.py
- animate_over_dim(da, dim: str, fps=10, out="anim.mp4") -> str
colors.py
- load_cpt(path) -> Colormap
- load_act(path) -> Colormap
- load_rgb(path) -> Colormap
state.py
- dump_state(dict) -> str (JSON)
- load_state(str) -> dict
5) UI Spec (Gradio Blocks)
Sidebar:
- File open (local, URL, S3)
- Dataset vars: pick A, optional B; operation (sum/avg/diff)
- Axes: X, Y; slice others (sliders, dropdowns)
- Plot type: 1D, 2D image, 2D contour, Map
- Projection: PlateCarree, Robinson, etc
- Colormap: dropdown + upload CPT/ACT/RGB
- Colorbar options; vmin/vmax; levels
- Animation: dim=[time|lev], FPS, MP4 export
- Export: PNG/SVG/PDF
- Save/load view state JSON
Main Panel:
- Figure canvas (matplotlib)
- Metadata panel: units, attrs, dims
6) Acceptance Criteria
- Open ERA5 (Zarr/OPeNDAP) dataset.
- Plot: (a) global 2D map with Robinson projection; (b) time–lat section; (c) 1D time series.
- Perform A–B difference contour plot.
- Load custom CPT colormap and export as SVG/PDF.
- Animate over time dimension (24 frames), export MP4.
- Save view state, reload reproduces identical figure.
7) Testing Checklist
- Local netCDF, remote OPeNDAP, public S3, Zarr open successfully.
- Variable discovery works; CF axis inference correct.
- 1D/2D/Map plotting functional.
- Combine A±B correct (aligned grid).
- Custom CPT colormap applied correctly.
- Export PNG/SVG/PDF correct dimensions/DPI.
- Animation over time produces correct frame count, valid MP4.
- Large datasets responsive due to Dask.