Generate and critique journalistic data visualizations — chart-form choice, encoding, and a corpus-backed critic
Project description
vizier
Building journalistic data visualizations — generating and critiquing. vizier helps make the graphics that carry a data story: it recommends the right chart form and encoding, and — with a corpus of critical writing — judges what a finished chart got wrong. It answers the parts of a chart that are actually decidable, and refuses the ones that aren't honest.
Generation and critique live side by side on purpose — they share the same DNA. The thresholds that let vizier suggest a form or palette are the thresholds it critiques against, so what it proposes is what it would pass. Kept distinct, the two halves can even be pointed at each other: a generator proposes, the critic pushes back.
- Computable (deterministic, no LLM, no keys) — chart-form recommendation and
structural checks, plus colorblind-safe palette generation + validation, ordinal ramps,
and legible ink. What vizier suggests is what vizier would pass. The color math is a
faithful port of the
datavizmethod's validator (same thresholds, same Machado-2009 colorblind transforms). - Corpus-backed critique (optional, LLM) — retrieval-augmented judgment of an existing chart against a library of critique writing, with prior-art citation.
It's built to be called by an agent or a generator (like a charting tool) over MCP, so
the tool asks vizier for the right decision instead of re-deriving it. It's the decision +
critique companion to weaver, which renders the
graphics.
Install
pip install datavizier # the computable toolkit + pattern query + MCP server
pip install "datavizier[search]" # + semantic retrieval (find_similar); pulls onnxruntime
pip install "datavizier[critique]" # + LLM critique/eval (needs an LLM gateway; see below)
pip install "datavizier[ingest]" # + rebuild the corpus from source
The distribution is datavizier on PyPI; the import package and CLI are both vizier
(import vizier, vizier …). The core has no proprietary and no heavyweight
dependencies — validate, suggest, recommend, analyze, and ink work from
pip install datavizier alone.
Quickstart — the computable toolkit (no keys)
# generation — give me one that's right
vizier guide "district budget module with per-pupil trend and revenue mix" --n-series 5
vizier recommend-form "composition of a total over time" --n-series 5
vizier suggest-palette 6 # a CVD-safe categorical palette, validated
vizier suggest-ramp 5 --hue navy # a one-hue ordinal ramp, validated
vizier ink "#0072b2" # the legible text color for a fill
# critique — is this right?
vizier validate "#e69f00,#0072b2,#009e73,#56b4e9" --pairs all
vizier analyze chart.svg # palette + structural checks from SVG/HTML
Every suggestion is validated before it's returned (colorblind ΔE via Machado-2009, WCAG contrast, OKLCH lightness/chroma). A request that can't be satisfied — a 9th categorical hue, too many ordinal steps for a warm hue — errors clearly rather than returning something that fails. See docs/computed-color-checks.md.
MCP server
vizier mcp serves everything above (plus the corpus query) as an MCP stdio server, so
Claude Code / Cursor / any MCP client can call it. Register it:
claude mcp add vizier -- vizier mcp
Tools: validate_palette, suggest_palette, suggest_ramp, ink_on,
analyze_artifact, check_contrast, recommend_form, implementation_guide,
plus corpus query
(search, find_similar, list_patterns, get_pattern, list_rubrics, …).
Setup + troubleshooting: docs/mcp-setup.md.
Chart pattern library + reader
vizier ships 43 chart-form patterns (FT Visual Vocabulary families) — each with when-to-use / when-not / alternatives / common-mistakes / reading-checklist. Browse them or route to one:
vizier patterns list
vizier recommend-form --family Flow
docs/reader/ is a self-contained static guide (open docs/reader/index.html, or the
published site — see below) that renders the whole library with live d3 demos, generated
from the pattern data (vizier patterns export -o docs/reader/data.json). It vendors its
own d3 and design tokens — no build step, no external dependencies.
Website
The landing page and the chart-forms guide are served from GitHub Pages out of docs/
(docs/index.html + docs/reader/, with .nojekyll so the static files serve as-is).
Regenerate the guide's data whenever patterns change:
vizier patterns export -o docs/reader/data.json
Corpus (rebuild your own)
vizier's critique is sharpened by a corpus of data-viz writing (award commentary, critique blogs, practitioner walkthroughs). Only vizier's own authored content ships — the 43 patterns, the rubrics, the FT-vocabulary parse, and the weaver principles. The third-party sources are not redistributed (they're copyrighted); rebuild them locally:
vizier ingest all # fetch + parse into corpus/<source>/
vizier db build --embed # index for search + retrieval
Set VIZIER_CORPUS_ROOT=/absolute/path/to/corpus-root before running
vizier ingest or vizier db build to write/read a corpus outside the installed
package tree. This is how the private corpus artifact is rebuilt without copying
private source material into the public package.
What the corpus draws on and why is described in INFLUENCES.md; the
per-source ingest notes are in docs/process-notes-sources.md.
Fetching is pluggable (src/vizier/ingest/_common.py): the bundled default is httpx;
point $VIZIER_FETCHER at a richer fetcher, or set your own FETCHER.
If you keep a private or local corpus DB with the same schema, keep it out of the distributed package and point Vizier at it at runtime — this is the plug point for proprietary prior art, so nothing private ever ships in the public package:
VIZIER_PRIVATE_DB=/absolute/path/to/private/.vizier.db vizier db search "reader decision"
VIZIER_EXTENSION_DBS=/absolute/path/to/private/.vizier.db vizier db search "reader decision"
VIZIER_EXTENSION_DBS="/path/one.db:/path/two.db" vizier mcp
Extension DBs are opened read-only and merged into the read-side corpus APIs:
search, find_similar, lookup, list_sources, list_principles,
list_rubrics, list_patterns, get_pattern, and stats.
VIZIER_EXTRA_DB_PATHS is accepted as an alias for the same path-list. As a
convenience, Vizier also auto-discovers an extension DB in a sibling
vizier-private/corpus/vizier-private.db; set VIZIER_AUTO_PRIVATE=0 to disable
that and run against the public corpus only.
Critique + evaluation (optional)
vizier critique <image> and the vizier eval harness use an LLM. vizier routes calls
through somm (an LLM gateway); provide a key in
.env (copy .env.example). The color-CVD case under evals/ demonstrates the
measured lift from the computable findings — see docs/computed-color-checks.md.
The vizier ↔ weaver split
vizier is the critique + decision companion to weaver,
which renders graphics. weaver draws the pixels; vizier decides which form and which
colors, and judges the result. The same thresholds serve both directions — see
PRINCIPLES.md.
Development
uv sync
uv run pytest -q # also runnable per-file: python tests/test_color.py
uv run ruff check src/ tests/
Both run in CI on every PR and push (.github/workflows/ci.yml, Python 3.12–3.13).
MIT licensed. Contributions welcome — see CONTRIBUTING.md. Release process and versioning: RELEASING.md; notable changes: CHANGELOG.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datavizier-0.1.0.tar.gz.
File metadata
- Download URL: datavizier-0.1.0.tar.gz
- Upload date:
- Size: 621.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff3c2edae098c8db5224c7d9c4767d84c7239a3d4d5f53237726390172ee2975
|
|
| MD5 |
4ca0a687c432015cb82dd5463f928e0f
|
|
| BLAKE2b-256 |
6175eff59f65966ba9470b99321f2a05d64ca541e2e3dcbd81be9abea3ff4fee
|
Provenance
The following attestation bundles were made for datavizier-0.1.0.tar.gz:
Publisher:
publish.yml on lavallee/vizier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datavizier-0.1.0.tar.gz -
Subject digest:
ff3c2edae098c8db5224c7d9c4767d84c7239a3d4d5f53237726390172ee2975 - Sigstore transparency entry: 2143293192
- Sigstore integration time:
-
Permalink:
lavallee/vizier@6b4fab45739a9524486723c45002cf17642fd841 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lavallee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b4fab45739a9524486723c45002cf17642fd841 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file datavizier-0.1.0-py3-none-any.whl.
File metadata
- Download URL: datavizier-0.1.0-py3-none-any.whl
- Upload date:
- Size: 143.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b131b840d15bf07f52e3dfca911b701e20e1c5bf58d6564681343a5af93d58f
|
|
| MD5 |
9f5857d86291b1561427b020620ef0a0
|
|
| BLAKE2b-256 |
2464611c004d8c190a9a618f5193f959dabdf9e16d2ba958f0ca7c90a08a35fd
|
Provenance
The following attestation bundles were made for datavizier-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on lavallee/vizier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datavizier-0.1.0-py3-none-any.whl -
Subject digest:
2b131b840d15bf07f52e3dfca911b701e20e1c5bf58d6564681343a5af93d58f - Sigstore transparency entry: 2143293207
- Sigstore integration time:
-
Permalink:
lavallee/vizier@6b4fab45739a9524486723c45002cf17642fd841 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lavallee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b4fab45739a9524486723c45002cf17642fd841 -
Trigger Event:
workflow_dispatch
-
Statement type: