{"id":51336233,"url":"https://github.com/vlevasseur073/copernicus_viewer","last_synced_at":"2026-07-02T03:03:24.166Z","repository":{"id":365505039,"uuid":"1272285053","full_name":"vlevasseur073/copernicus_viewer","owner":"vlevasseur073","description":"A Rust GUI application to visualize Copernicus satellite data compatible with EOPF format","archived":false,"fork":false,"pushed_at":"2026-06-25T16:46:35.000Z","size":1526,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T18:22:03.498Z","etag":null,"topics":["copernicus","earth-observation","eopf","gui","visualization","zarr"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vlevasseur073.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T13:14:22.000Z","updated_at":"2026-06-25T16:46:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vlevasseur073/copernicus_viewer","commit_stats":null,"previous_names":["vlevasseur073/copernicus_viewer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vlevasseur073/copernicus_viewer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vlevasseur073%2Fcopernicus_viewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vlevasseur073%2Fcopernicus_viewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vlevasseur073%2Fcopernicus_viewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vlevasseur073%2Fcopernicus_viewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vlevasseur073","download_url":"https://codeload.github.com/vlevasseur073/copernicus_viewer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vlevasseur073%2Fcopernicus_viewer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35030921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["copernicus","earth-observation","eopf","gui","visualization","zarr"],"created_at":"2026-07-02T03:03:23.138Z","updated_at":"2026-07-02T03:03:24.156Z","avatar_url":"https://github.com/vlevasseur073.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Copernicus Viewer\n\nA Rust GUI application to explore and visualize [EOPF](https://cpm.pages.eopf.copernicus.eu/eopf-cpm/main/PSFD/index.html) Zarr products.\n\n## Features\n\n- Open EOPF Zarr stores (`.zarr` directories, `.zarr.zip` archives, or `s3://` URIs on AWS S3)\n- Open Sentinel-3 SAFE products (`.SEN3` directories) when built with the `safe` feature\n- Browse the product hierarchy (groups and variables) in a tree view\n- Inspect metadata with an xarray-inspired representation (DataTree / Group / DataArray with attributes)\n- **Product attributes** tree for root metadata (nested STAC / EOPF attributes, foldable like the hierarchy)\n- **Statistics and data preview** tables in the inspector for loaded array subsets\n- **Async plot loading** with progress bar for large arrays\n- **Geo-referenced plotting**: coordinate arrays, CRS, and axis extent labels on heatmaps\n- **CF flag variables** with `flag_meanings` and `flag_values` / `flag_masks` (bitmask plots per flag)\n- **Coverage map** in the inspector — adaptive Plate Carrée view (zooms to regional tiles, global view for wide footprints) with Natural Earth coastlines\n- **Product comparison** (**Tools → Comparison**) — compare a reference and a new product (structure, variable data, CF flags) with user-defined thresholds and a pass/fail report; same logic via the `compare_products` example\n- **S3 product download** — copy an open S3-hosted product to a local `.zarr` directory (**File → Download product…**, hierarchy **⬇** icon, or right-click on the product name)\n\n## Quick start\n\nThis walkthrough opens a reference and a new EOPF product side by side (the screenshots below use Sentinel-3 SLSTR LST data). Pass your own `.zarr` paths:\n\n```bash\ncargo run -- /path/to/reference.zarr /path/to/new.zarr\n```\n\nBoth products appear in the **Hierarchy** panel. Select **`measurements/lst`** to inspect metadata, view the coverage map, and plot the land-surface temperature heatmap:\n\n![Explore SLSTR LST — side-by-side plots at full and 50% resolution](docs/screenshots/01-explore-lst.png)\n\nConfigure S3 bucket credentials from **File → Configure S3…**:\n\n![S3 bucket configuration dialog](docs/screenshots/06-s3-config.png)\n\nOpen **Tools → Comparison**, pick the reference and new product, then run the check. The report lists structure, variable, and flag differences — here four auxiliary variables differ while 64 measurement variables pass:\n\n![Product comparison — reference vs reprocessed SLSTR LST](docs/screenshots/05-comparison.png)\n\nThe same comparison logic is available from the CLI:\n\n```bash\ncargo run --example compare_products -- /path/to/reference.zarr /path/to/new.zarr\n```\n\nTo regenerate the README screenshots (maintainers):\n\n```bash\nCOPERNICUS_VIEWER_CAPTURE_DEMO=docs/screenshots cargo run -- \\\n  /path/to/reference.zarr /path/to/new.zarr\n```\n\nFor further details, see the [tutorial](docs/TUTORIAL.md).\n\n## Requirements\n\n- Rust 1.75+\n- GPU support for the GUI (**wgpu** on Linux desktop, macOS, and Windows; **Glow**/OpenGL on WSL2 — see [WSL2 graphics](#wsl2-graphics))\n\n### Sentinel-3 SAFE (optional `safe` feature)\n\nThe `safe` Cargo feature enables `.SEN3` support via NetCDF. It is **on by default** for local development.\n\n| Build | Command | NetCDF at build time | Runtime install |\n|-------|---------|----------------------|-----------------|\n| Default (Zarr + SAFE, system libs) | `cargo build` | `libnetcdf-dev` (Linux) | None for NetCDF if you ship `-safe` with `netcdf-static` |\n| Self-contained SAFE binary | `cargo build --features netcdf-static` | cmake + C++ toolchain | None — NetCDF/HDF5/zlib embedded |\n| Zarr-only (no SAFE) | `cargo build --no-default-features --features dialog-portal` | None | N/A |\n\n**GitHub Releases** ship two variants per platform: a Zarr-only binary and a `-safe` binary built with `netcdf-static` (no NetCDF install required for end users).\n\nOn Linux, system development builds need:\n\n```bash\nsudo apt install libnetcdf-dev\n```\n\nWithout `libnetcdf-dev`, use static linking:\n\n```bash\ncargo build --features netcdf-static\n```\n\n### WSL2 / Linux system packages\n\nOn **WSLg** (default on recent WSL2), the app uses Wayland automatically — no extra packages needed.\n\nIf you use **X11 forwarding** to an external X server (VcXsrv, X410, …), install:\n\n```bash\nsudo apt install libxkbcommon-x11-0 libgl1-mesa-dri\n```\n\nRuntime for the GTK file dialog (optional build): `libgtk-3-0`.\n\n**Opening products:** **File → Open Zarr…** opens an in-app browser for local `.zarr` directories, `.zarr.zip` archives, and (when built with `safe`) `.SEN3` SAFE directories — click or double-click a product, or paste a path and press **Open**. Use **S3** in that dialog to browse configured buckets and prefixes on object storage (see [S3 object storage](#s3-object-storage)). You can also paste an `s3://bucket/path/product.zarr` URI directly. Use **System picker…** for the native file chooser on local paths; it automatically uses a folder picker for `.zarr` paths and a file picker for `.zip` paths. You can open several products at once; each appears as a top-level entry in the **Hierarchy** panel. Close one with **✕** next to its name or **File → Close product**. Opening a product reads hierarchy metadata only; array values are loaded when you select a variable to plot.\n\nIf the native dialog is empty or opens twice on WSL, rebuild with the GTK backend:\n\n```bash\nsudo apt install libgtk-3-dev\ncargo build --no-default-features --features dialog-gtk\ncargo run --no-default-features --features dialog-gtk\n```\n\n### WSL2 graphics\n\nThe app picks a renderer from your WSL environment (override with `COPERNICUS_VIEWER_GL`):\n\n| Environment | Default | Backend |\n|-------------|---------|---------|\n| WSLg (Wayland) | GPU OpenGL | Glow |\n| WSL + X11 forwarding | Mesa llvmpipe (software) | Glow |\n| Linux desktop / macOS / Windows | GPU | wgpu |\n\nOn **WSLg** (`WAYLAND_DISPLAY` set), the default is **Glow with GPU acceleration**. Mesa llvmpipe is not compatible with WSLg/Wayland.\n\nOn **WSL over X11** (VcXsrv, X410, …), the default is **Glow with Mesa llvmpipe** software rendering, which is much more stable than ZINK/EGL when resizing windows. Vsync is disabled on this path; the app sets `LIBGL_ALWAYS_SOFTWARE=1` and related Mesa env vars automatically.\n\n```bash\n# Force Mesa llvmpipe + Glow (X11 only; on WSLg falls back to GPU Glow with a warning)\nCOPERNICUS_VIEWER_GL=software cargo run\n\n# GPU: Glow on WSL, wgpu elsewhere\nCOPERNICUS_VIEWER_GL=hardware cargo run\n\n# Force wgpu everywhere (expert — may fail on WSL with EGL/ZINK errors)\nCOPERNICUS_VIEWER_GL=wgpu cargo run\n\n# Explicit auto-detection (same as unset)\nCOPERNICUS_VIEWER_GL=auto cargo run\n```\n\n`native` is an alias for `wgpu`.\n\n## Install\n\n### Rust (crates.io)\n\n```bash\ncargo install copernicus_viewer\ncopernicus_viewer\n```\n\nRequires a Rust toolchain and GPU support (same as [Requirements](#requirements)).\n\n### Prebuilt binaries (GitHub Releases)\n\nDownload the archive for your platform from [GitHub Releases](https://github.com/vlevasseur073/copernicus_viewer/releases), extract it, and run:\n\n- **`copernicus_viewer-{version}-{target}.tar.gz` / `.zip`** — Zarr-only (no `.SEN3` support)\n- **`copernicus_viewer-{version}-{target}-safe.tar.gz` / `.zip`** — Zarr + Sentinel-3 SAFE (self-contained NetCDF)\n\n```bash\n# Linux / macOS\n./copernicus_viewer /path/to/product.zarr\n\n# Windows\ncopernicus_viewer.exe C:\\path\\to\\product.zarr\n```\n\nVerify downloads with the `SHA256SUMS.txt` file attached to each release.\n\n## Build \u0026 Run\n\n```bash\n# Optional: generate a local sample product for testing\ncargo run --example create_sample_zarr\n```\n\n### Formatting and linting\n\n```bash\ncargo fmt --all\ncargo clippy --locked --all-targets -- -D warnings\ncargo test --locked\n```\n\nCI runs `cargo fmt --check`, Clippy (`-D warnings`), and tests on every push and pull request.\n\nOptional [pre-commit](https://pre-commit.com) hooks run `cargo fmt` and Clippy before each commit:\n\n```bash\npip install pre-commit   # or: brew install pre-commit\npre-commit install\npre-commit run --all-files   # verify without committing\n```\n\n```bash\n# Compare two products from the CLI (reference vs new)\ncargo run --example compare_products -- reference.zarr new.zarr\n\ncargo run\n```\n\nUse **File → Open Zarr…** to load additional EOPF products. Pass one or more paths on the command line:\n\n```bash\ncargo run -- /path/to/product_a.zarr /path/to/product_b.zarr\ncargo run -- s3://my-eopf-bucket/eopf/products/S03OLCEFR_202309.zarr\n```\n\n## S3 object storage\n\nRemote EOPF Zarr directory stores on AWS S3 (including custom endpoints) can be opened with an `s3://` URI from the command line or by pasting the URI in **File → Open Zarr…**. You can also browse remote products in that dialog: click **S3** to list buckets from your config file, then navigate prefixes and double-click a `.zarr` product to open it. Use **Local** to return to filesystem browsing. The in-app directory listing for local paths is unchanged.\n\n### Credentials\n\nCredentials are resolved in this order (bucket name from the URI selects the INI section):\n\n1. Config file from `COPERNICUS_VIEWER_S3_CONFIG` or `S3_CONFIG` (if set)\n2. Default config at `%APPDATA%\\cp-rs\\s3.conf` (Windows) or `~/.config/cp-rs/s3.conf` (Unix)\n3. `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_ENDPOINT`, `S3_REGION`\n4. `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_ENDPOINT_URL`, `AWS_REGION`\n\nINI format (rclone-style), one section per bucket:\n\n```ini\n[my-eopf-bucket]\ntype = s3\naccess_key_id = AKID\nsecret_access_key = SKEY\nregion = eu-west-1\nendpoint = https://s3.example.com\n```\n\nNested paths are resolved to the Zarr product root automatically (same as local paths), e.g. `s3://bucket/path/product.zarr/measurements/lst` opens `s3://bucket/path/product.zarr`.\n\n`.zarr.zip` archives on S3 are not supported in this version.\n\n### Downloading S3 products\n\nWhen an S3 product is open, download it to your local filesystem as a `.zarr` directory:\n\n- **File → Download product…** (enabled when the selected product is on S3)\n- **⬇** next to the product name in the **Hierarchy** panel\n- Right-click the product name → **Download product…**\n\nChoose a parent folder in the native dialog; the product is saved as `\u003cfolder\u003e/\u003cproduct-name\u003e.zarr` with the same Zarr layout as on S3. Progress appears in the status bar. The download fails if that destination folder already exists.\n\nThe library API [`download_s3_product`](src/zarr/download.rs) is also available for scripts and automation.\n\n## Releasing (maintainers)\n\n1. Bump `version` in `Cargo.toml` and commit.\n2. Create and push an annotated tag: `git tag -a v0.2.0 -m \"v0.2.0\" \u0026\u0026 git push origin v0.2.0`\n3. Ensure the repository secret `CARGO_REGISTRY_TOKEN` is set ([crates.io token](https://crates.io/settings/tokens)).\n\nThe [release workflow](.github/workflows/release.yml) runs tests, builds binaries for Linux, Windows, and macOS (x86_64 + arm64), attaches them to a GitHub Release, publishes to crates.io, and updates [`CHANGELOG.md`](CHANGELOG.md) from git history using [git-cliff](https://git-cliff.org).\n\nPreview unreleased changes locally (set `GITHUB_TOKEN` for PR metadata from the GitHub API):\n\n```bash\ncargo install git-cliff --locked\nexport GITHUB_TOKEN=ghp_...   # optional; `gh auth token` works too\ngit cliff --config cliff.toml --unreleased\n```\n\nTo include linked issues in the changelog, reference them in commit or PR descriptions (`Fixes #123`, `Closes #456`, or `#789`). git-cliff does not query the GitHub Issues API for all closed issues in a release — only PR metadata (via the API) and issue numbers mentioned in commit text (via `link_parsers` in [`cliff.toml`](cliff.toml)).\n\nRegenerate the full changelog:\n\n```bash\ngit cliff --config cliff.toml --output CHANGELOG.md\n```\n\nFor the **first** crates.io publish, create an API token at [crates.io/settings/tokens](https://crates.io/settings/tokens), add it as a GitHub secret, then either push a tag or run locally:\n\n```bash\ncargo publish\n```\n\n## EOPF Zarr structure\n\nEOPF products follow the standard Zarr hierarchy described in [PSFD §4.4](https://cpm.pages.eopf.copernicus.eu/eopf-cpm/main/PSFD/4-storage-formats.html#zarr-representation-of-eopf-data-products):\n\n- Root `.zattrs` — product-level metadata (STAC attributes)\n- `.zmetadata` — consolidated metadata\n- Group directories (`measurements`, `quality`, `conditions`, …) with `.zgroup`\n- Variable leaf directories with `.zarray`, `.zattrs`, and chunk files\n\nSample data is available from the [EOPF Sentinel Zarr Samples Service](https://zarr.eopf.copernicus.eu/).\n\nCoastline data: [Natural Earth 110m land](https://www.naturalearthdata.com/) (public domain).\n\n## License\n\nLicensed under either of:\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n- MIT license ([LICENSE-MIT](LICENSE-MIT))\n\nat your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvlevasseur073%2Fcopernicus_viewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvlevasseur073%2Fcopernicus_viewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvlevasseur073%2Fcopernicus_viewer/lists"}