Skip to main content

Enhanced matplotlib styling, color management, and utility library for publication-quality figures

Project description

dartwork-mpl

PyPI version Python versions License: MIT CI Docs

Publication-quality matplotlib — a thin utility layer, not a wrapper.

dartwork-mpl keeps Figure / Axes 100% native and adds the parts matplotlib makes tedious: a physical-width geometry API, curated style presets, an OKLCH-aware color system, deterministic content-aware layout, visual validation, and a first-class integration for AI coding assistants (an MCP server + a bundled prompt corpus). You never learn a new plotting API — you keep writing matplotlib, just without the friction.

import matplotlib.pyplot as plt
import dartwork_mpl as dm

dm.style.use("scientific")                                       # 1. curated preset
fig, ax = plt.subplots(figsize=dm.figsize("13cm", "standard"))   # 2. physical width × aspect
ax.plot(x, y, color="oc.blue5", lw=dm.lw(0))
ax.set_xlabel("Time [s]")
dm.simple_layout(fig)                                            # 3. content-aware margins
dm.save_formats(fig, "figure", formats=("svg", "png", "pdf"))    # 4. multi-format save

That four-step pattern — preset → figsize(width, aspect)simple_layoutsave_formats — is the whole workflow. No tight_layout(), no hand-tuned figsize=(w, h) arithmetic, no dpi= guesswork.


Installation

pip install dartwork-mpl        # or:  uv add dartwork-mpl

Requires Python 3.10+. The core install is intentionally lean; add an extra only when you need it:

Extra Enables Pulls in
[notebook] dm.show() inline SVG display in Jupyter ipython
[mcp] the MCP server for AI assistants fastmcp, httpx
[ui] the interactive parameter viewer fastapi, uvicorn
pip install "dartwork-mpl[notebook]"   # or [mcp], [ui]

Highlights

  • Geometry, decoupled from inches. dm.figsize("13cm", "standard") takes a physical width (cm / in / mm / pt, or dm.col1 = 9 cm / dm.col2 = 17 cm) and one of six aspect tokens (square / portrait / standard / golden / wide / cinema); the height follows. Bare numbers are rejected so the unit is always explicit.
  • Deterministic layout. simple_layout(fig) measures every visible artist and places the GridSpec arithmetically — reproducible across machines, unlike tight_layout()'s heuristics. margin="2%" (or dm.mm(2)) adds a buffer.
  • OKLCH-aware color. Named palettes (oc.* Open Color, tw.* Tailwind, md.*, ad.*, cu.*, pr.*) plus a Color class spanning OKLab / OKLCH / RGB / hex with perceptual interpolation (cspace) and gamut-correct mapping.
  • Curated styling. Seven presets (scientific, report, presentation, …), each with a Korean -kr variant, and preset-relative scaling helpers fs / fw / lw so literals never drift when you switch themes.
  • Validation & export. validate_figure(fig) flags overflow, text/legend overlap, tick crowding, and empty axes — invisible failures in headless agent pipelines. save_formats(fig, ...) writes SVG / PNG / PDF / EPS at once.
  • AI-native. A bundled MCP server exposes lint + auto-fix, figure validation, color lookup, and the live policy corpus to Claude Code / Cursor / Windsurf. No-MCP agents read the same corpus from disk.
  • Batteries included. Material Design Icons + Font Awesome 6 fonts, ready-made plot templates (plot_diverging_bar, …), and a FastAPI viewer for live tuning.

Core API at a glance

import dartwork_mpl as dm

# ── Geometry ──────────────────────────────────────────────────────────
dm.figsize("13cm", "wide")          # width × aspect token  → inch tuple
dm.figsize("13cm", 0.6)             # ...or a numeric ratio / "8cm" / dm.cm(8)
dm.cm(13); dm.mm(170); dm.inch(4.6); dm.pt(24)   # Length values
dm.col1; dm.col2                    # 9 cm / 17 cm academic-column sugar

# ── Styling & scaling ─────────────────────────────────────────────────
dm.style.use("scientific")          # apply a preset
dm.style.stack(["base", "font-scientific", "lang-kr"])   # compose
dm.fs(2); dm.fw(1); dm.lw(-0.3)     # preset-relative font size / weight / line width

# ── Color ─────────────────────────────────────────────────────────────
ax.plot(x, y, color="oc.blue5")     # named palettes register with matplotlib
dm.color("oc.blue5")                # parse name / "#4285F4" / "rgb(...)" / "oklch(...)"
dm.oklch(0.7, 0.15, 150); dm.rgb(66, 133, 244); dm.hex("#4285F4")
dm.cspace("#FF0000", "#0000FF", n=5, space="oklch")      # perceptual interpolation
dm.mix_colors("oc.blue5", "white", alpha=0.35)

# ── Layout & annotation ───────────────────────────────────────────────
dm.simple_layout(fig)               # deterministic content-aware margins
dm.simple_layout(fig, margin="2%", gs=gs)   # buffer + target a GridSpec
dm.label_axes(axes)                 # (a) (b) (c) panel labels
dm.arrow_axis(ax, "x", "Cost")      # Low ◄── Cost ──► High

# ── Validate, export, icons ───────────────────────────────────────────
dm.validate_figure(fig)             # overflow / overlap / tick-crowding / empty
dm.save_formats(fig, "fig", formats=("png", "svg", "pdf"), dpi=300)
mdi = dm.icon_font("mdi")           # also "fa-solid" / "fa-regular" / "fa-brands"

# ── Plot templates ────────────────────────────────────────────────────
from dartwork_mpl.templates import plot_diverging_bar
fig, ax = plot_diverging_bar(labels=["A", "B"], neg_values=[-30, -15], pos_values=[40, 55])

See the usage guide and API reference for the full surface.


Style presets

Preset Use case
scientific Compact fonts for academic papers and journals
report Reports and dashboards, cleaner spines
minimal Tufte-style, data-ink focus — no spines or ticks
presentation Large fonts for projected slides
poster Extra-large fonts and thick lines for posters
web On-screen readability for docs and notebooks
dark Dark backgrounds for Jupyter and dark-mode slides

Each has a Korean -kr variant (scientific-kr, report-kr, …) with Korean-aware fonts. List them with dm.list_styles().


AI-assisted development (MCP)

dartwork-mpl ships a built-in Model Context Protocol server so AI coding assistants pull the current policy guides, color palettes, lint catalog, and helper tools straight into the chat — no copy-pasting docs. It exposes 13 tools (lint + auto-fix, figure validation, render, color lookup, info), 12 resources + 3 resource templates (the prompt corpus + 18 plot templates), and 2 prompts.

pip install "dartwork-mpl[mcp]"     # installs fastmcp + httpx; adds the dartwork-mpl-mcp script

Point your client at the dartwork-mpl-mcp console script — e.g. Claude Code (~/.claude.json) or Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "dartwork-mpl": { "command": "dartwork-mpl-mcp" }
  }
}

Restart the client and ask it to list its MCP resources to confirm. Windsurf, Antigravity, generic stdio setups, the full tool/resource catalog, and the local-clone variant are covered in docs/integrations/mcp_server.md.

No MCP? The same corpus is bundled in the wheel and reachable from Python — dm.get_agent_doc("llms-full") (also "AGENTS", "CLAUDE", "llms") returns the text, dm.agent_doc_path(name) its path. The repo-root CLAUDE.md / AGENTS.md / llms.txt (per the llmstxt.org spec) are the 30-second onboarding.


Documentation

📚 Full documentation


Migrating from earlier versions

The 0.3 names (dm.SW / MW / TW / DW, dm.FS_*, dm.WIDTHS, dm.cm2in, dm.agent_utils, dm.xplot), the 0.4-era figure constructors (dm.subplots, dm.figure), and the 0.5 prompt-corpus installer (dm.install_llm_txt and friends) have all been removed. Every old access path raises AttributeError / ModuleNotFoundError naming its replacement — the canonical pattern is plt.subplots(figsize=dm.figsize("13cm", "standard")) with a separate dm.style.use(...). Full mapping: docs/migration.md · CHANGELOG.


Project layout

src/dartwork_mpl/
├── units.py / scale.py        # figsize, cm/mm/inch/pt, col1/col2 · fs/fw/lw
├── style.py                   # Style class + preset management
├── colors/                    # Color (OKLab/OKLCH/RGB/hex) + named palettes
├── layout.py / annotation.py  # simple_layout, label_axes, arrow_axis
├── validate.py / lint.py      # validate_figure · lint + migrate_legacy_code
├── io.py / formatting.py      # save_formats, show · format_axis_*
├── icon.py / font.py / cmap.py / diagnostics/   # fonts, colormaps, viz helpers
├── templates/ / helpers/      # plot templates · high-level composition helpers
├── agent.py / prompt.py       # bundled LLM corpus · prompt guides
├── mcp/                       # MCP server (server / resources / tools / prompts)
├── ui/                        # interactive FastAPI viewer
└── asset/                     # bundled styles, colors, fonts, icons, prompts

Contributing & issues

Bug reports and feature requests go to the GitHub issue tracker. Released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dartwork_mpl-0.5.0.tar.gz (28.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dartwork_mpl-0.5.0-py3-none-any.whl (28.9 MB view details)

Uploaded Python 3

File details

Details for the file dartwork_mpl-0.5.0.tar.gz.

File metadata

  • Download URL: dartwork_mpl-0.5.0.tar.gz
  • Upload date:
  • Size: 28.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dartwork_mpl-0.5.0.tar.gz
Algorithm Hash digest
SHA256 34df19b327acf3380a23edfc1f4948459afb22c83a4c4c6e22ffaa9f3ad9d5ed
MD5 f817ad9e5b832850643a68a6a0676a21
BLAKE2b-256 31f6cc4f031fd52695931a0c0cbfbbc323a8f1574d22767d40b56fecc883b0d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for dartwork_mpl-0.5.0.tar.gz:

Publisher: release.yml on dartworklabs/dartwork-mpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dartwork_mpl-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: dartwork_mpl-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 28.9 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dartwork_mpl-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 55897a930bff5a370f078ac59b37da4721ef14fc8a5dd13f0f10fd88c35c93e8
MD5 b4e02798a3623b01aa34ff3f7b251232
BLAKE2b-256 2442d53c1f6186effeef399debcd063a824888a3427e482ce6b26c88e4c7a89d

See more details on using hashes here.

Provenance

The following attestation bundles were made for dartwork_mpl-0.5.0-py3-none-any.whl:

Publisher: release.yml on dartworklabs/dartwork-mpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page