diff --git a/README.md b/README.md index 6bb1900..143e1e4 100644 --- a/README.md +++ b/README.md @@ -1,433 +1,232 @@ -# hyper +# Hyper -**hyper** provides native 3D hypergraph exploration for **Python scientific -workflows** and **embedded Rust applications**. Explore explicit group memberships -with picking, search, lasso selection, and neighborhood isolation. +**A native 3D hypergraph viewer for Python workflows and Rust applications.** -The Rust core provides HIF interchange, projections, and force-directed layout -without Bevy. The typed Python package exposes HIF interchange and can launch -the separately installed native viewer. Use scientific libraries for analysis -and Hyper to explore their exported datasets. +A hypergraph represents a group relationship as one edge connecting any number +of nodes: authors on a paper, participants in an interaction, or modules in a +dependency group. Hyper lets you inspect those memberships, find overlapping +groups, and explore neighborhoods with search, picking, and lasso selection. -[![Animated Mathlib source dependency atlas: 9,384 nodes, 37,356 imports, and 7,550 dependency groups](docs/media/mathlib.gif)](docs/media/mathlib.mp4) +[Try the viewer](#try-the-viewer) · [Use Python](#use-from-python) · +[Use Rust](#use-from-rust) · [Documentation](#documentation) -**[Watch the full-resolution Mathlib demo](docs/media/mathlib.mp4)** — the complete source-file -import graph of mathlib v4.34.1, rendered at 1080p. Includes 9,112 source files -and 272 external-module placeholders. The video uses a settled layout; -[reproduction instructions and live benchmarks](docs/mathlib-demo.md) explain -the workload and rendering limits. +[![Mathlib module dependency groups in Hyper's native 3D viewer](docs/media/mathlib.gif)](docs/media/mathlib.mp4) -## Choose a workflow +[Full-resolution Mathlib demo](docs/media/mathlib.mp4) · +[Reproduce the demo](docs/mathlib-demo.md). +The recording uses a settled layout; it is not a live-layout performance test. -| Workflow | Entry point | -|---|---| -| Exchange scientific datasets from Python | `hyper_viz.HifDocument`: load, validate, retain metadata, and export HIF | -| Explore a dataset in a native 3D window | `hyper` CLI or Python `hyper_viz.show()` | -| Embed projections and layout in a Rust application | Bevy-free `hyper-viz` library and render-independent scene | -| Embed the native viewer in a Rust host | `hyper-viz-bevy` plugin and live scene channel | - -Inputs include scientific **HIF**, native **`hypergraph.v1`** JSON, and supported -legacy exports. The model is domain-agnostic: vertices, hyperedges, and memberships. - -## Python and scientific interoperability +## Try the viewer -Install the **`hypergraph-viz`** Python distribution with **CPython 3.10+**: +Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then open +the built-in coauthorship demo: ```bash -python -m pip install hypergraph-viz +uvx --python 3.12 --from hypergraph-viz-viewer hyper ``` -The import name is `hyper_viz`. Wheels cover Linux x86_64, macOS arm64/x86_64, -and Windows x86_64; a compatible wheel requires no Rust compiler. Install the native desktop viewer through the optional extra: +No project, repository checkout, or Rust compiler is needed. `--from` selects +the package that supplies the `hyper` executable. To open your own dataset: ```bash -python -m pip install --upgrade "hypergraph-viz[viewer]" +uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json ``` -Use `--upgrade` when the core package is already installed so pip selects the -release that provides the viewer extra. The viewer needs a desktop session and -graphics driver. Linux desktop wheels -require glibc 2.28+; macOS targets 11.0+. Rust is needed only for source builds. -For a Python development build from this checkout with **Rust 1.89+**: +Requires a **desktop session and working graphics drivers**. Prebuilt viewer +wheels support Linux x86_64 (glibc 2.28+), macOS arm64/x86_64 (11.0+), and +Windows x86_64. The viewer opens on the machine running the command. +See [platform requirements](docs/DESKTOP_PACKAGE.md). -```bash -python -m venv .venv -. .venv/bin/activate # Windows: .venv\Scripts\activate -python -m pip install maturin==1.9.6 -cd crates/hyper-viz-python -maturin develop --locked -cd ../.. -``` +Once the window opens, drag to orbit, scroll to zoom, and click a node or group +to inspect it. Press **Space** to pause the layout, **F** to frame the camera, +or **Cmd+F / Ctrl+F** to search. Press **Enter** in search to isolate matching +neighborhoods. The [viewer guide](docs/VIEWER.md#controls) covers all controls. -```python -import hyper_viz +## Use from Python -document = hyper_viz.HifDocument.load("dataset.hif.json") -document.save("roundtrip.hif.json") -print(document.to_json()) +Create a project and install the API with its matching desktop viewer: -# Install hypergraph-viz[viewer] first. -viewer = hyper_viz.show(document, projection="bipartite") -exit_code = viewer.wait() # or viewer.close() to terminate +```bash +uv init --python 3.12 hyper-example +cd hyper-example +uv add "hypergraph-viz[viewer]" ``` -Pass `executable="/path/to/hyper"` to select a viewer explicitly. Otherwise the -launcher finds the matching companion package, then `hyper` on PATH. The launcher -validates compatibility, starts the process asynchronously without a shell, and -owns a temporary native snapshot that is cleaned up after exit. The Python -extension itself does not depend on Bevy or download a viewer. - -Keep the `HifDocument` for scientific export: it preserves JSON values, record -order, metadata, integer/string ID identity, isolated nodes, empty edges, and -incidence properties. Whitespace and object-key order are not preserved. -Validation uses a bundled, pinned schema and works offline. - -**Document interchange supports more semantics than the viewer.** Viewer -conversion accepts undirected memberships and rejects directed or simplicial -semantics, incidence direction, weights, or attributes, and duplicate identities -or memberships. Node/edge weights round to finite `f32` for viewing; original -numbers remain in the document. Validation and compatibility exceptions expose -`location` and `reason`. Retained attributes are not automatically mapped to -viewer colors or exposed by the stock inspector. - -See [HIF and Python integration](docs/HIF.md) for API details, generated typing, -wheel builds, and runnable [XGI](crates/hyper-viz-python/examples/xgi_interop.py) -and [Julia](examples/hif_interop.jl) interchange examples. Direct scientific -object adapters, notebook embedding, layout bindings, and live updates from -Python are deferred. The [notebook prototype roadmap](docs/NOTEBOOK_ROADMAP.md) -sets out an anywidget canvas probe and Bevy/WASM feasibility checks. - -## Ecosystem fit and measured findings - -Hyper complements scientific analysis libraries and offers a Rust/native route -to exploring groups. The ecosystem comparison suggests this positioning; user -preference and adoption have not been measured. - -| Tool family | Fit alongside Hyper | -|---|---| -| XGI, HyperNetX, Hypergraphx | Scientific analysis and figures; exchange datasets through HIF where semantics are compatible | -| HyperGodot | Dedicated interactive 2D hypergraph exploration; an alternative when a 2D workflow fits | -| Sigma.js, Cytoscape.js, 3d-force-graph | Browser graph components; represent groups through incidence adapters and custom drawing | -| Graphia, Gephi | General graph analysis and attribute-driven exploration; useful references for richer inspection and filtering | - -The [October 3, 2026 benchmark](docs/benchmarks/ecosystem-2026-10-03/README.md) -records **445 measured attempts across 89 configurations** on one Apple M5 Pro -Mac. Scientific figures, browser rendering, native rendering, and import/save -workflows are separate tracks; these results do not establish an overall speed -ranking or native-versus-browser speed advantage. - -| Finding | Evidence and implication | -|---|---| -| Dense hulls are expensive | For 1,000 nodes / 2,000 groups in frozen bipartite mode, median per-run p95 application interval rose from **9.68 ms** without hulls to **62.08 ms** with hulls; both completed 5/5 attempts. Profile geometry and update costs before adding visual effects. | -| A successful demo is not a capacity guarantee | Full Mathlib bipartite runs completed 0/5 attempts within the 180-second budget in each frozen mode. Star mode with hulls and the default label policy completed 5/5, but frozen p95 was **219.91 ms**. Projection and settings change both work and responsiveness. | -| Failures need investigation | **16/120 native attempts** did not complete, including a small fixture. Completed-run timings exclude those failures; their cause remains unresolved. | -| Model fidelity must be checked | XGI preserved every tested model record. Our HNX adapter omitted isolated nodes and empty groups; HGX merged parallel groups by membership. Keep the original HIF document and validate adapter boundaries. | -| Smooth navigation does not guarantee fast updates | Sigma completed all 35 browser attempts, but its Mathlib update command took **13.24 s**. Update strategies differed across tools; evaluate updates separately from camera motion. | - -Application intervals and browser callback cadence are not GPU timings or -input-to-visible latency. Hulls approximate large groups, representations differ, -and display refresh was not locked across browser batches. Read the -[method and limitations](docs/benchmarks/ecosystem-2026-10-03/methodology.md), -[raw results](docs/benchmarks/ecosystem-2026-10-03/summary.csv), and -[rerun instructions](scripts/benchmarks/README.md) before interpreting timings. - -The next priorities are **attribute inspection and filtering**, **measured -responsiveness during dense geometry updates**, and **easier installation with -accurate documentation**. The [community and ecosystem research](docs/ecosystem-comparison.md) -explains the evidence behind those priorities. Browser distribution, directed -rendering, and timeline views remain outside the current viewer scope. - -## Docs for external readers - -| Doc | Contents | -|---|---| -| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Package boundary, host coupling policy | -| [docs/API.md](docs/API.md) | Library API overview | -| [docs/VIEWER.md](docs/VIEWER.md) | How to run the viewer + example scene | -| [docs/HIF.md](docs/HIF.md) | Scientific interchange, Python API, supported semantics, and packaging | -| [Measured ecosystem comparison](docs/benchmarks/ecosystem-2026-10-03/README.md) | Results, completion counts, raw evidence, and limitations | -| [Community and ecosystem research](docs/ecosystem-comparison.md) | Positioning and roadmap evidence | -| [Notebook prototype roadmap](docs/NOTEBOOK_ROADMAP.md) | Small-dataset anywidget plan and WASM feasibility checks | -| [Python release guide](docs/PYTHON_RELEASE.md) | PyPI Trusted Publisher setup and tag-based releases | -| [docs/PUBLIC_RELEASE_CHECKLIST.md](docs/PUBLIC_RELEASE_CHECKLIST.md) | Maintainer release-decision checklist | -| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup and PR norms | - -## Use as a library +In an existing uv project using CPython 3.10+, run only `uv add`. +uv manages the environment and lockfile; `uv run` needs no activation. -```toml -# Headless: schema, JSON, projections, 3D layout (no Bevy) -hyper-viz = { git = "https://github.com/atomicstrata/hyper.git" } +Save this as `explore.py`. It creates two papers with a shared author, saves a +HIF dataset, and opens the viewer: -# Optional native 3D window -hyper-viz-bevy = { git = "https://github.com/atomicstrata/hyper.git" } -``` - -Path dep while this repo sits next to the host: +```python +import json +import hyper_viz -```toml -hyper-viz = { path = "../hyper/crates/hyper-viz" } -hyper-viz-bevy = { path = "../hyper/crates/hyper-viz-bevy" } +document = hyper_viz.HifDocument.from_json(json.dumps({ + "network-type": "undirected", + "nodes": [{"node": name} for name in ["alice", "bob", "carol", "dana"]], + "edges": [{"edge": "paper-a"}, {"edge": "paper-b"}], + "incidences": [ + {"node": "alice", "edge": "paper-a"}, + {"node": "bob", "edge": "paper-a"}, + {"node": "carol", "edge": "paper-a"}, + {"node": "bob", "edge": "paper-b"}, + {"node": "dana", "edge": "paper-b"}, + ], +})) +document.save("papers.hif.json") + +viewer = hyper_viz.show(document) +viewer.wait() # Keep the script running until the window closes. ``` -`hyper-viz` has **no Bevy dependency**. Embed it in a WASM, SVG, or custom renderer. - -### Headless - -```rust -use hyper_viz::prelude::*; - -let graph = Hypergraph::new() - .with_title("Reactions") - .vertex("h2o", "H2O", "molecule") - .vertex("h2", "H2", "molecule") - .vertex("o2", "O2", "molecule") - .hyperedge("combust", ["h2", "o2", "h2o"], "2H2 + O2 → 2H2O"); - -let scene = graph.project(Projection::Bipartite); -let mut layout = ForceLayout3D::from_scene(&scene, LayoutConfig::default()); -layout.step(); +```bash +uv run explore.py ``` -Load JSON (automatic HIF, native, or supported legacy format detection): +For existing data, replace the constructor with +`document = hyper_viz.HifDocument.load("dataset.hif.json")`. +You can also open the saved example with `uv run hyper papers.hif.json`. -```rust -use hyper_viz::{from_json_str, load_json}; - -let graph = load_json("fixtures/sample.json")?; -let graph = from_json_str(r#"{"version":"hypergraph.v1","vertices":[],"hyperedges":[]}"#)?; -``` +| Name | Purpose | +|---|---| +| `hypergraph-viz` | Python distribution for HIF validation and interchange | +| `hypergraph-viz[viewer]` | Python API plus the matching `hypergraph-viz-viewer` distribution | +| `hyper_viz` | Python import | +| `hyper` | Desktop viewer executable | -A quarantined one-way importer can still load a legacy host export prefix; it is -**not** part of the public domain model (see architecture docs). +For interchange alone, install `hypergraph-viz` and omit the `show()` and +`wait()` calls. The API works without a desktop or Bevy. Use `uv run` for +project scripts; `uvx` runs tools in a separate environment and the API package +has no executable. See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/). -### Native viewer +
+Use pip instead of uv -```rust -use hyper_viz_bevy::{run_from_graph, run_visualizer, run_visualizer_live}; +Requires CPython 3.10+. With Python 3.12 installed, create a virtual environment: -run_from_graph(graph); // bipartite + blocking window -run_visualizer(scene); // already projected -run_visualizer_live(scene, rx, None); // host thread pushes scenes +```bash +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install --upgrade "hypergraph-viz[viewer]" +hyper ``` -A new scene on the live channel (or a file-watch reload) rebuilds the scene -while retaining positions by stable ID and remapping surviving selection and -focus. Invalid watched input leaves the previous scene visible. - -### Embed in a Bevy app - -```rust -use bevy::prelude::*; -use hyper_viz_bevy::HyperVisualizerPlugin; +On Windows, create it with `py -3.12 -m venv .venv` and activate it in +PowerShell with `.venv\Scripts\Activate.ps1`. Run the example with +`python explore.py`. For the API alone, install `hypergraph-viz`. +If installation reports no matching distribution, check `python --version`; +upgrading pip does not upgrade Python. + +
+ +## Data and scientific use + +The viewer reads [HIF](docs/HIF.md) (Hypergraph Interchange Format) and native +`hypergraph.v1` JSON, detecting the format automatically. See the +[native JSON example](docs/VIEWER.md#example-scene) and +[projection guide](docs/VIEWER.md#quick-start) for `bipartite` (default), +`clique`, and `star` projections, and `--watch` for file reloads. + +Hyper complements analysis tools such as [XGI](https://github.com/xgi-org/xgi), +[HyperNetX](https://github.com/pnnl/HyperNetX), and +[Hypergraphx](https://github.com/HGX-Team/hypergraphx). Export supported data to +HIF, explore it in Hyper, and keep your analysis in the original library. +The [XGI example](crates/hyper-viz-python/examples/xgi_interop.py) demonstrates +export and round-trip interchange. + +Before using a visualization in research: + +- **Check viewer compatibility.** The viewer supports undirected memberships. + Directed or simplicial semantics and incidence properties are rejected during + conversion. HIF document interchange preserves richer data; keep the original + `HifDocument` for export. See [supported semantics](docs/HIF.md#supported-semantics). +- **Read hulls as visual aids.** Large groups use approximate hulls. Confirm + membership in the selection panel; spatial proximity is a layout result. +- **Measure your workload.** Dense hulls can be expensive. The + [benchmarks](docs/benchmarks/ecosystem-2026-10-03/README.md) report completion + counts, methods, and limits; they do not establish an overall speed ranking. + +Hyper is **early-stage software**. The current Python API exposes HIF +interchange and viewer launching; Rust exposes projections and layout too. +The viewer opens a native window, including when launched from Python. +Notebook embedding, live Python updates, and direct scientific-library object +adapters are not yet available; see the [notebook roadmap](docs/NOTEBOOK_ROADMAP.md) +for browser plans. + +## Use from Rust + +The `hyper-viz` core handles JSON I/O, projections, and 3D force layout without +Bevy or a window. Add it to your application's `Cargo.toml`: -App::new() - .add_plugins(DefaultPlugins) - .add_plugins(HyperVisualizerPlugin::from_scene(scene)) - .run(); +```toml +[dependencies] +hyper-viz = { git = "https://github.com/atomicstrata/hyper.git" } ``` -`VisualizerConfig` sets window title and size for the standalone helpers. -Pass `Some(shutdown_flag)` to `run_visualizer_live` so a host thread can exit -the Bevy app. +Build and lay out a group: -## Crate map +```rust +use hyper_viz::prelude::*; -```text -HIF JSON → HifDocument → compatibility check -Native JSON / Rust builder API - → Hypergraph - → project(Bipartite | Clique | Star) - → HypergraphScene # render-agnostic IR - → ForceLayout3D # Barnes-Hut octree, CPU - → hyper-viz-bevy # native 3D window (optional) +fn main() { + let graph = Hypergraph::new() + .vertex("alice", "Alice", "person") + .vertex("bob", "Bob", "person") + .vertex("carol", "Carol", "person") + .hyperedge("paper-a", ["alice", "bob", "carol"], "Paper A"); + + let scene = graph.project(Projection::Bipartite); + let mut layout = ForceLayout3D::from_scene(&scene, LayoutConfig::default()); + layout.step(); + println!("{} layout nodes", layout.positions.len()); +} ``` -| Crate | Role | Depend on this? | -|---|---|---| -| [`crates/hyper-viz`](crates/hyper-viz) | HIF, scene IR, projections, layout, hulls, JSON I/O | **Yes** — library | -| [`crates/hyper-viz-bevy`](crates/hyper-viz-bevy) | Bevy 0.18 + egui native viewer | Only if you want the window | -| [`crates/hyper-viz-python`](crates/hyper-viz-python) | Typed Python HIF bindings and viewer launcher; no Bevy | For Python workflows | -| `hyper` (this binary) | CLI: load JSON or open the built-in demo | No — not a library | +Add `hyper-viz-bevy` from the same Git repository for a standalone window or a +plugin in an existing Bevy app. The [Rust API guide](docs/API.md) covers viewer +embedding and live scene updates; [architecture](docs/ARCHITECTURE.md) explains +the crate boundaries. Rust builds require **1.89+**. -## Quick start (CLI) +
+Run from source ```bash -# Built-in coauthorship demo -cargo run - -# Example scene -cargo run -- fixtures/sample.json - -# Scientific HIF dataset (also auto-detected without --format) -cargo run -- dataset.hif.json --format hif - -# Hot-reload while you edit the file -cargo run -- --watch fixtures/sample.json - -# Other projections: bipartite (default), clique, star -cargo run -- --projection clique fixtures/sample.json - -# Headless library example (no window) -cargo run -p hyper-viz --example project_scene -``` - -Requires Rust 1.89+. The first Bevy build can take several minutes, depending -on the machine. For regular use, build with `cargo build --release --bin hyper` -or install with `cargo install --path . --locked`. See [docs/VIEWER.md](docs/VIEWER.md) -for native viewer setup. - -## JSON schema (`hypergraph.v1`) - -```json -{ - "version": "hypergraph.v1", - "meta": { "id": "g1", "title": "Coauthorship" }, - "vertices": [ - { "id": "alice", "label": "Alice", "kind": "person" }, - { "id": "bob", "label": "Bob", "kind": "person" }, - { "id": "carol", "label": "Carol", "kind": "person" } - ], - "hyperedges": [ - { "id": "paper-a", "label": "Paper A", "vertices": ["alice", "bob", "carol"] } - ] -} +git clone https://github.com/atomicstrata/hyper.git +cd hyper +cargo run --locked --release -- fixtures/sample.json ``` -| Field | Required | Notes | -|---|---|---| -| `vertices[].id` | yes | Stable id referenced by hyperedges | -| `vertices[].label` | no | Falls back to `id` | -| `vertices[].kind` | no | Free-form; used only for color | -| `vertices[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` | -| `hyperedges[].vertices` | yes | Member vertex ids | -| `hyperedges[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` | -| `*.attrs` | no | Opaque JSON map for the host app | - -## How the graph is drawn - -Default projection is **bipartite** (one extra-node hub per hyperedge). The -viewer hides those hubs by default so the hyperedge is read as a **set**: - -| Arity | Drawing | -|---|---| -| 2 | Colored line between the two members | -| 3 | Triangle hull | -| 4 | Tetrahedron hull | -| 5+ | Convex hull, using at most 24 sampled members | - -Large-group hulls are approximate: the geometry cap does not remove memberships -from the graph, and a hull is not an exact membership boundary. Empty edges have -no drawable geometry. - -Each hyperedge keeps a **stable hue** from its id (hash), so nested sets stay -distinguishable. Nested hulls are inflated slightly to avoid z-fighting. -Vertex color comes from `kind` (fixed palette for well-known names, hash otherwise). - -Uncheck **Hide extra-node hubs** in the Hyperedge hulls panel to show the -bipartite hubs as spheres. - -## Controls - -Left button is dual-purpose. **Drag** orbits; **click** (press + release with -almost no movement) selects. Orbiting does not change selection. - -| Input | Action | -|---|---| -| Left drag | Orbit camera (selection is kept) | -| Left click | Select the vertex or hyperedge under the cursor | -| Click empty space | Clear selection | -| Shift / Cmd + click | Add to selection | -| Scroll | Zoom (HUD windows steal scroll when the pointer is over them) | -| Lasso (UI panel) | Polygon select (disables orbit while on) | -| Space | Toggle force layout | -| A | Isolate `attention` status: hide other hulls, boost remaining fills, label those nodes | -| F | Frame camera (ignored while the find bar is focused) | -| ⌘F / Ctrl+F | Focus the find bar | -| ⌃⌘F | Isolate the selected incident neighborhood (toggle) | -| / | Focus the find bar (when not typing) | -| Enter (in find) | Isolate the match neighborhood and frame the camera | -| Esc | Clear the find query, or clear focus | -| Clear selection | Button in the Selection window | - -The find bar at the bottom highlights matches as you type (BM25 + Jaro–Winkler -on label, id, kind, and status). Hits use the existing selection glow and the -**Selection** window. While focus is on, each new query also re-isolates the -match neighborhood and reframes the camera. - -The **Selection** window lists selected hyperedges and vertices with kind, -label, status, and a location taken from the id (`repo:…`, `wt:…`, `pr:…`). -Click a row to narrow the selection to that node. Pointer over any HUD window -does not orbit or zoom the scene. - -Picking hits vertices, hull triangles, and arity-2 segments. Hidden hubs are -not pickable. - -## Hover vs selected - -Both states keep the object's own hue. They do **not** swap to a highlight -color. - -| State | Look | -|---|---| -| Hover | Nodes grow slightly; hull/line wires brighten | -| Selected | Same hue, higher saturation and glow | -| Hover + selected | Selected treatment wins (still a bit larger) | - -## Projections - -- **Bipartite** (default): one hub node per hyperedge + incidence links (Ouvrard extra-node). -- **CliqueExpansion** (`--projection clique`): all pairs within each hyperedge (no hubs). -- **StarCentroid** (`--projection star`): centroid attraction, no hub nodes. - -## Tests +The native viewer requires a desktop graphics environment; the first build can +take several minutes. To run the core example without a window: ```bash -cargo test -p hyper-viz -cargo test -p hyper-viz-bevy --lib -cargo clippy -p hyper-viz -p hyper-viz-bevy --all-targets -- -D warnings +cargo run --locked -p hyper-viz --example project_scene ``` -## Observability +See the [viewer guide](docs/VIEWER.md) for more commands, and the +[Python build instructions](docs/HIF.md#python-installation) for extension development. -JSON-friendly `tracing` logs on scene init, file-watch reload, and live-channel -reload (`nodes`, `hyperedges`, `graph_id`). Set `RUST_LOG=hyper_viz_bevy=info` -(see [`.env.example`](.env.example)). +
-No secrets. The viewer restores HUD, navigation (lasso), camera pose, -selection, focus neighborhood, and find query from a `hyperviz.session.v1` -JSON blob: +## Documentation -| Host | Where | +| Guide | What you'll find | |---|---| -| Desktop | `~/Library/Application Support/hyper-viz/session.json` (macOS), `%APPDATA%/hyper-viz/session.json` (Windows), `$XDG_CONFIG_HOME/hyper-viz/session.json` (Linux) | -| Browser (wasm) | `localStorage["hyperviz.session.v1"]` | - -Override the file with `HYPER_VIZ_SESSION=/path/to/session.json`. Set -`HYPER_VIZ_SESSION=off` to disable. Prefs (including navigation) are global; -camera / selection / isolate are keyed by graph id. Layout positions are not -stored. - -## License - -Dual-licensed under **MIT OR Apache-2.0**. See [LICENSE](LICENSE), -[LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and -[NOTICE](NOTICE). +| [Viewer](docs/VIEWER.md) | Setup, controls, projections, display settings, and saved sessions | +| [Python and HIF](docs/HIF.md) | Interchange, Python API, scientific semantics, and source builds | +| [Rust API](docs/API.md) | Build graphs, run layouts, and embed the viewer | +| [Architecture](docs/ARCHITECTURE.md) | Crate responsibilities and integration boundaries | +| [Benchmarks](docs/benchmarks/ecosystem-2026-10-03/README.md) | Measured results, methods, and limitations | -## Directory layout +For questions or bug reports, [open an issue](https://github.com/atomicstrata/hyper/issues). +To contribute, start with [CONTRIBUTING.md](CONTRIBUTING.md) for development +setup, checks, and pull request guidelines. -```text -crates/hyper-viz/ # library other projects depend on -crates/hyper-viz-bevy/ # optional Bevy renderer -crates/hyper-viz-python/ # Python extension, typed package, and launcher -scripts/benchmarks/ # opt-in ecosystem benchmark harness -docs/ # API, interoperability, ecosystem research, benchmark evidence -fixtures/sample.json # coauthorship demo -src/main.rs # CLI -``` +If you use Hyper in research, record the package version or Git commit, +dataset, projection, and viewer settings so others can reproduce the view. -## Non-goals +## License -- PAOH timeline view -- WASM / browser serve (session JSON is ready for `localStorage`) -- Euler-style set diagrams (convex-hull member shells only) -- Bundling any proprietary memory engine +Dual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE). +See [NOTICE](NOTICE) for third-party notices. diff --git a/crates/hyper-viz-python/README.md b/crates/hyper-viz-python/README.md index fab45ad..1ca2292 100644 --- a/crates/hyper-viz-python/README.md +++ b/crates/hyper-viz-python/README.md @@ -7,10 +7,21 @@ The package includes generated extension type stubs, typed Python wrappers, and ## Installation +With [uv](https://docs.astral.sh/uv/getting-started/installation/), create a project +with a supported Python version and add the package: + ```sh -python -m pip install hypergraph-viz +uv init --python 3.12 hyper-example +cd hyper-example +uv add hypergraph-viz ``` +uv manages `.venv` and `uv.lock`, and can download Python 3.12 if needed. +Save your Python code as `explore.py` and run it with `uv run explore.py`. +In an existing uv project, run only `uv add hypergraph-viz`. +Alternatively, use `python -m pip install hypergraph-viz` in a Python 3.10+ +virtual environment. Upgrading pip does not upgrade Python. + Requires standard CPython 3.10 or newer. Platform wheels cover Linux x86_64, macOS arm64/x86_64, and Windows x86_64; installing a compatible wheel requires no Rust compiler. Building from source requires Rust 1.89 or newer and maturin. @@ -40,12 +51,30 @@ not preserved. ## Launch the native viewer -Install the matching prebuilt desktop viewer with the optional extra: +From your uv project, install the matching prebuilt desktop viewer: ```sh -python -m pip install --upgrade "hypergraph-viz[viewer]" +uv add "hypergraph-viz[viewer]" +uv run hyper ``` +`uv run hyper` opens the built-in demo; use +`uv run hyper dataset.hif.json --projection bipartite` for your own dataset. +For pip, use `python -m pip install --upgrade "hypergraph-viz[viewer]"`. + +To launch only the desktop viewer without creating a project: + +```sh +uvx --python 3.12 --from hypergraph-viz-viewer hyper +# Open your dataset: +uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json +``` + +`--from` selects the distribution that supplies the `hyper` executable. +`hypergraph-viz` supplies the Python API and has no executable of its own; +use `uv add "hypergraph-viz[viewer]"` for Python integration in a project. +See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/). + Wheels cover Linux x86_64, macOS arm64/x86_64, and Windows x86_64. No Rust compiler or repository checkout is needed on these platforms. A desktop session and graphics driver are required. Linux viewer wheels require glibc 2.28+; @@ -53,9 +82,13 @@ macOS wheels target 11.0+. Notebook kernels on remote machines cannot open a window on your laptop; see the [notebook prototype roadmap](https://github.com/atomicstrata/hyper/blob/python-v0.1.2/docs/NOTEBOOK_ROADMAP.md). -Then launch it from Python: +Save the following as `explore.py` alongside `dataset.hif.json`, then run +`uv run explore.py`: ```python +import hyper_viz + +document = hyper_viz.HifDocument.load("dataset.hif.json") viewer = hyper_viz.show(document, projection="bipartite") exit_code = viewer.wait() # Or viewer.close() to terminate and clean up. diff --git a/docs/DESKTOP_PACKAGE.md b/docs/DESKTOP_PACKAGE.md index 15bad5b..941543d 100644 --- a/docs/DESKTOP_PACKAGE.md +++ b/docs/DESKTOP_PACKAGE.md @@ -1,12 +1,39 @@ # Hyper desktop viewer Prebuilt native viewer for [hypergraph-viz](https://pypi.org/project/hypergraph-viz/). -Install the Python API and matching viewer together: +Launch the built-in demo with [uv](https://docs.astral.sh/uv/getting-started/installation/): ```sh -python -m pip install --upgrade "hypergraph-viz[viewer]" +uvx --python 3.12 --from hypergraph-viz-viewer hyper ``` +Open your own dataset: + +```sh +uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json +``` + +`--from` selects this package, which supplies the `hyper` executable. +See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/). + +For Python integration, install the API and matching viewer in a project: + +```sh +uv init --python 3.12 hyper-example +cd hyper-example +uv add "hypergraph-viz[viewer]" +``` + +In an existing uv project using Python 3.10+, run only `uv add`. +Save the Python example below as `explore.py` alongside `dataset.hif.json`, +then run `uv run explore.py`. No environment activation is needed. +uv can download Python 3.12 when necessary. +`hypergraph-viz` provides the Python API and has no executable of its own; +`uvx hypergraph-viz` cannot launch the viewer. + +For pip, use `python -m pip install --upgrade "hypergraph-viz[viewer]"` in a +Python 3.10+ virtual environment. + ```python import hyper_viz diff --git a/docs/VIEWER.md b/docs/VIEWER.md index 92c59ab..e12ab45 100644 --- a/docs/VIEWER.md +++ b/docs/VIEWER.md @@ -1,7 +1,31 @@ # Running the native viewer -The Bevy viewer is **native window only** (not a web app). First compile is -slow (~40s cold); subsequent runs are fast. +The Bevy viewer opens a native desktop window. It requires a desktop session +and working graphics drivers. + +## Install + +With [uv](https://docs.astral.sh/uv/getting-started/installation/), open the +prebuilt viewer without creating a project: + +```bash +uvx --python 3.12 --from hypergraph-viz-viewer hyper +uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json +``` + +Omitting the file opens the built-in coauthorship demo. `--from` selects the +distribution containing the `hyper` executable. For Python integration, use +`uv add "hypergraph-viz[viewer]"` in a CPython 3.10+ project and run scripts +with `uv run`; see the [complete Python example](../README.md#use-from-python). + +Alternatively, run `python -m pip install --upgrade "hypergraph-viz[viewer]"` +in a CPython 3.10+ virtual environment, then run +`hyper`. See [platform requirements](DESKTOP_PACKAGE.md) for supported wheels. + +For a source build, use Rust 1.89+ and run the commands below from this checkout. +The first Bevy build can take several minutes. For regular use, build with +`cargo build --release --bin hyper` or install with +`cargo install --path . --locked`. ## Quick start @@ -14,6 +38,9 @@ cargo run # Example scene (fixtures/sample.json) cargo run -- fixtures/sample.json +# Scientific HIF dataset (also detected without --format) +cargo run -- dataset.hif.json --format hif + # Hot-reload while editing JSON cargo run -- --watch fixtures/sample.json @@ -24,6 +51,18 @@ cargo run -- --projection clique fixtures/sample.json cargo run -p hyper-viz-bevy --example view -- fixtures/sample.json ``` +For prebuilt wheels, replace `cargo run --` with +`uvx --python 3.12 --from hypergraph-viz-viewer hyper`, `uv run hyper` in a +project with the viewer extra, or `hyper` in an activated pip environment. +`--watch` reloads the graph while retaining positions by stable ID and remapping +surviving selection and focus. Invalid input leaves the previous scene visible. + +The projections are: + +- **Bipartite** (default): one hub per hyperedge, connected to its members. +- **Clique**: links between every pair of members within each hyperedge. +- **Star**: attraction toward each hyperedge's centroid, without hub nodes. + Headless (no window) library smoke: ```bash @@ -50,7 +89,9 @@ Minimal shape: "version": "hypergraph.v1", "meta": { "id": "g1", "title": "Coauthorship" }, "vertices": [ - { "id": "alice", "label": "Alice", "kind": "person" } + { "id": "alice", "label": "Alice", "kind": "person" }, + { "id": "bob", "label": "Bob", "kind": "person" }, + { "id": "carol", "label": "Carol", "kind": "person" } ], "hyperedges": [ { "id": "paper-a", "label": "Paper A", "vertices": ["alice", "bob", "carol"] } @@ -58,22 +99,93 @@ Minimal shape: } ``` -## Controls (summary) +| Field | Required | Notes | +|---|---|---| +| `vertices[].id` | yes | Stable ID referenced by hyperedges | +| `vertices[].label` | no | Falls back to `id` | +| `vertices[].kind` | no | Free-form; used for color | +| `vertices[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` | +| `hyperedges[].id` | yes | Stable ID for the group | +| `hyperedges[].vertices` | yes | Member vertex IDs | +| `hyperedges[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` | +| `*.attrs` | no | Opaque JSON map for the host app | + +For scientific interchange and viewer compatibility, see the +[HIF guide](HIF.md#supported-semantics). + +## Controls + +Left drag orbits; a click with almost no movement selects. Orbiting keeps the +current selection. Pointer input over a UI panel does not orbit or zoom the scene. | Input | Action | |---|---| | Left drag | Orbit (keeps selection) | | Left click | Select vertex / hyperedge | | Click empty | Clear selection | +| Shift / Cmd + click | Add to selection | | Scroll | Zoom | +| Lasso (UI panel) | Polygon selection; disables orbit while enabled | | Space | Toggle force layout | +| A | Isolate `attention` status: hide other hulls, boost remaining fills, label those nodes | +| F | Frame the camera (ignored while typing in search) | | ⌘F / Ctrl+F | Find bar | +| ⌃⌘F | Toggle isolation of the selected incident neighborhood | +| / | Find bar (when not typing) | +| Enter (in find) | Isolate the match neighborhood and frame the camera | | Esc | Clear find / focus | +| Clear selection | Button in the Selection window | + +The find bar highlights matches as you type. Search covers label, ID, kind, and +status using BM25 and Jaro–Winkler matching. While neighborhood focus is active, +each new query also isolates the matches and reframes the camera. + +The **Selection** window lists selected hyperedges and vertices with kind, +label, status, and a location taken from the ID (`repo:…`, `wt:…`, `pr:…`). +Click a row to narrow the selection to that node. Picking hits vertices, hull +triangles, and two-member segments. Hidden hubs are not pickable. + +## Display settings + +The default bipartite projection adds a hub for each hyperedge. Hubs are hidden +by default so groups appear as sets. Uncheck **Hide extra-node hubs** in the +**Hyperedge hulls** panel to show them as spheres. + +| Group size | Drawing | +|---|---| +| 2 | Colored line between members | +| 3 | Triangle hull | +| 4 | Tetrahedron hull | +| 5+ | Convex hull using at most 24 sampled members | -Full interaction notes live in the [root README](../README.md). +Large-group hulls are approximate. The geometry cap does not remove memberships, +and a hull is not an exact membership boundary. Empty edges have no drawable +geometry. + +Each hyperedge has a stable hue derived from its ID. Nested hulls are inflated +slightly to avoid overlapping surfaces flickering. Vertex color comes from +`kind`, using a fixed palette for known names and a hash otherwise. + +Hover and selection keep the object's hue: + +| State | Appearance | +|---|---| +| Hover | Nodes grow slightly; hull and line wires brighten | +| Selected | Higher saturation and glow | +| Hover + selected | Selection treatment wins; nodes still grow slightly | ## Session persistence -Desktop writes `hyperviz.session.v1` under the OS config dir -(`hyper-viz/session.json`). Override with `HYPER_VIZ_SESSION=/path` or disable -with `HYPER_VIZ_SESSION=off`. +The viewer restores UI preferences, navigation (including lasso), camera pose, +selection, neighborhood focus, and the find query from a `hyperviz.session.v1` +JSON file. + +| Platform | Default file | +|---|---| +| macOS | `~/Library/Application Support/hyper-viz/session.json` | +| Windows | `%APPDATA%/hyper-viz/session.json` | +| Linux | `$XDG_CONFIG_HOME/hyper-viz/session.json`, or `~/.config/hyper-viz/session.json` when unset | + +Override the file with `HYPER_VIZ_SESSION=/path/to/session.json`, or set +`HYPER_VIZ_SESSION=off` to disable persistence. Preferences are global; camera, +selection, and focus are keyed by graph ID. Layout positions are not stored. diff --git a/docs/readme-research.md b/docs/readme-research.md new file mode 100644 index 0000000..927a7a8 --- /dev/null +++ b/docs/readme-research.md @@ -0,0 +1,134 @@ +# README communication research + +Reviewed October 5, 2026 (America/Lima), while consolidating documentation PRs +[#10](https://github.com/atomicstrata/hyper/pull/10) and +[#11](https://github.com/atomicstrata/hyper/pull/11). + +## Purpose and method + +The README must help a scientist explore a supported dataset and help a developer +integrate Hyper without first learning the entire implementation. Success means a +reader can identify the tool’s purpose, choose the correct package, run a complete +example, and understand the representation’s limits. + +This review examined ten primary-source READMEs: four hypergraph projects, three +graph visualization projects, and three scientific or spatial visualization +projects with native viewers or multiple language interfaces. The latter are +communication references, not claims of feature equivalence. Sources below are +pinned to the most recent commit modifying each README on its default branch at +the time of retrieval. Their linked assets and tutorials were inspected as README +entry points; competitor installation instructions and applications were not run. + +The review considered six questions: what problem the introduction communicates; +how a reader chooses a workflow; how installation handles prerequisites and +package names; whether the first example supplies its data and execution context; +how semantics, limitations, and research use are explained; and where API, +contributor, and maintenance details live. Observations describe the documents; +the recommendations are editorial judgments. No user study or conversion-rate +measurement was performed, and this is not a performance comparison. + +## Project-by-project findings + +| Primary source | Comparison role | Observed communication | Applied lesson for Hyper | +|---|---|---|---| +| [xgi-org/xgi](https://github.com/xgi-org/xgi/blob/b8164bca1ce6b8b5c613223c33365dc61e432f28/README.md) | Scientific hypergraphs | Defines the model and supported operations, links a gallery and datasets, and provides citation and contribution routes. Installation leads to external user guides rather than an inline first example. | Explain group relationships and ecosystem fit; retain visible scientific and contributor routes. Supply a complete first example in Hyper itself. | +| [pnnl/HyperNetX](https://github.com/pnnl/HyperNetX/blob/17534c3806a3666e421881b3fb314e787024a6b5/README.md) | Scientific hypergraphs | Connects HIF to other libraries and provides Colab tutorials. Release history, maintainer credits, environment choices, and developer tooling occupy substantial space before and after installation. | Explain HIF interoperability, but keep release history, build variants, and long analysis outside the landing README. | +| [HGX-Team/hypergraphx](https://github.com/HGX-Team/hypergraphx/blob/a71d3c2c2f97fc8d9e7492a633a87668d6b4ab67/README.md) | Scientific hypergraphs | Introduces group interactions with familiar domains, then installs and constructs a small graph before showing metadata and analysis. Separate tutorials and citation guidance support deeper use. | Use a concrete coauthorship example before API details. Keep advanced semantics in the HIF guide rather than copying HGX’s analysis scope. | +| [pnnl/hypernetx-widget](https://github.com/pnnl/hypernetx-widget/blob/11a9f59551e131928367fee092d8bbbb80bde6b0/README.md) | Interactive hypergraphs | Starts with a browser demo, then a notebook example that defines its own graph and shows the resulting widget. Explains selection and alternate representations with screenshots and interactions. | Offer an immediate demo and explicit first interactions. State that Hyper opens a native window; put the full interaction reference in the viewer guide. | +| [graphia-app/graphia](https://github.com/graphia-app/graphia/blob/d7c339c5cc94575edfad39cdfb49b84ea86e1f10/README.md) | Desktop graph exploration | Pairs a short purpose statement with a video and domain-specific applications. Links a user guide and separates help from building, but gives source-build commands rather than a short packaged launch walkthrough. | Keep the visual demo and recognizable use cases. Make the packaged viewer command directly available, with source builds later. | +| [vasturiano/3d-force-graph](https://github.com/vasturiano/3d-force-graph/blob/2a901f53eb9b427635c74f20bfdf0cfc4b3812bc/README.md) | Browser 3D graph component | Shows a linked visual preview and a large gallery whose demos link to source. Follows a short integration sketch with extensive API tables. The sketch uses placeholder container and data arguments. | Keep a reproducible visual example and concise developer entry point. Use defined inputs and move exhaustive API material into dedicated guides. | +| [jacomyal/sigma.js](https://github.com/jacomyal/sigma.js/blob/a923c1676c4f035a6f1b98a465f0d4bd39df6b34/README.md) | Browser graph component | Names both required packages, then shows imports, nodes, an edge, and renderer creation. Separates project use from local development and links documentation, Storybook, and a demo. | Make package roles explicit and show a small constructed dataset. Separate consuming the library from contributing or building it. | +| [nmwsharp/polyscope](https://github.com/nmwsharp/polyscope/blob/63c09627e8252050e7be50e9de9cdeb40cc42799/README.md) | Scientific native 3D viewer | Explains its structure/quantity model and integration philosophy, then gives parallel C++ and Python examples and citation guidance. Example arrays are supplied by the reader. | Give Python and Rust distinct routes and explain the core/viewer boundary. Improve first-run completeness by constructing all example data. | +| [napari/napari](https://github.com/napari/napari/blob/bb3fdfda8567fc84284b1b721553cf1e6bf1da3c/README.md) | Scientific Python desktop viewer | Offers a uvx trial before environment installation, tells users how to open sample data, and distinguishes interactive-shell use from scripts that need an event loop. Includes roadmap, citation, and help routes. | Lead with a standalone uvx demo and retain a project workflow. Include viewer.wait() in the Python script and state where the window opens. | +| [rerun-io/rerun](https://github.com/rerun-io/rerun/blob/44bb79b9c65357f3ee57c2fdf616281243269dfc/README.md) | Rust and Python visualization SDK | Connects purpose to concrete workflows, separates language onboarding from viewer installation, and documents active development, limitations, and research citation. Its short code taste assumes pre-existing arrays. | Explain SDK/viewer installation and evolving scope. Preserve measured limitations without reproducing a benchmark report or assuming missing example data. | + +## What the comparison changes + +### One entry point per reader task + +A single README has three real entry points here: try the desktop viewer, use +Python with a dataset, and integrate the Rust core. These are tasks rather than +skill levels. A scientist may write Rust and a developer may only need the CLI. +Top-level jump links let either reader choose immediately. The viewer trial comes +first because it demonstrates the project without a checkout or a new Python +project. The documented Python 3.12 command selects a supported interpreter rather +than relying on whichever system Python happens to be installed. + +The alternative of leading with Cargo and the architecture diagram makes every +new user perform developer setup. Leading with a generic pip command leaves the +package/command mismatch unresolved. Leading with a comparison or benchmark table +asks the reader to evaluate implementation details before they have seen a group. +Those materials remain available in the existing guides. + +### Complete examples and visible results + +The Python example defines four authors, two papers, and every incidence. The +shared author makes overlapping membership concrete, while saving HIF connects the +example to a real file workflow. It ends with show() and wait(), explains the +expected window, and supplies uv run explore.py. Readers need no unpublished +fixture or scientific-library installation. Existing data replaces the constructor +with HifDocument.load(). + +The Rust example is a complete main() with a small group, projection, layout step, +and printed node count. The dependency snippet uses the repository because the +Rust crates are not published. The core has no window dependency; optional Bevy +integration has a separate explanation and API link. Source-build instructions +remain available in an expandable section. + +### Scientific trust depends on boundaries + +A compelling screenshot cannot establish faithful interchange, exact hull +membership, analysis capabilities, or interactive performance. Hyper’s opening +explains membership exploration and later places three concise boundaries beside +the data workflow: viewer conversion accepts undirected memberships; large hulls +are approximate; and workload-specific benchmark results need their methods and +completion counts. Full scientific values belong to the original HifDocument. +The HIF guide remains authoritative for incidence properties, identity mapping, +precision changes, and metadata interpretation. + +The README positions Hyper alongside scientific analysis libraries through +supported HIF exchange. It does not imply that their in-memory objects can be +passed directly to show(). It distinguishes the Python API’s current interchange +and launcher surface from Rust’s layout API, and states that the native window is +not a notebook widget. The package metadata identifies the software as alpha, so +the README calls it early-stage without promising a stability policy. + +Scientific projects often provide publication citations or archived software +identifiers. Hyper has no CITATION.cff or verified project DOI in this checkout. +Rather than invent one, the README asks researchers to record the version or +commit, dataset, projection, and settings. A formal citation policy can be added +when maintainers establish one. + +### Link depth to a maintained guide + +PR #10’s useful change is progressive detail: essential actions on the landing +page, complete controls, schema fields, drawing behavior, and session persistence +in docs/VIEWER.md. PR #11’s useful change is installation reliability: the viewer +distribution for uvx, the matching viewer extra for Python projects, supported +Python, and uv run for scripts. The consolidation keeps both, then aligns the +viewer and package guides so navigation never returns a reader to conflicting +launch instructions. + +A compact package-name table resolves distribution, import, extra, and executable +roles. pip remains available for existing Python environments. Contributor checks +stay in CONTRIBUTING.md, and launcher internals stay in the Python/HIF guide. +The README retains one visual demo, with descriptive alternate text and a caption +that identifies the settled layout. Competitor marketing, capacity claims, and +visual assets were not copied. + +## Consolidation and verification criteria + +| Requirement | Result to review | +|---|---| +| Keep #10’s simpler entry page | Purpose, demo, three reader paths, short explanations, and guide links | +| Preserve #10’s viewer reference | Complete controls, drawing rules, schema example, and sessions in docs/VIEWER.md | +| Keep #11’s correct uv launch | uvx selects hypergraph-viz-viewer; Python projects install hypergraph-viz[viewer] | +| Preserve #11’s complete Python path | Project creation, example data, saved HIF, viewer lifetime, and script command | +| Align companion documentation | Python package and desktop package guides retain uv and pip workflows | +| Support Rust integration | Git dependency, compilable headless example, optional viewer boundary, source path | +| Support scientific interpretation | Interchange/viewing distinction, approximate hulls, benchmark link, reproducibility note | +| Avoid regressions in navigation | Check local paths, section anchors, code fences, and retained documentation | +| Check executable examples | Run published CLI help/version, Python construction/save/reload/conversion, and Rust example | + +This document records the editorial evidence. The consolidated PR records the +actual verification results, including any checks that did not exercise a GUI.