Enhanced matplotlib styling, color management, and utility library for publication-quality figures
Project description
dartwork-mpl
Enhanced matplotlib styling, color management, and utility library engineered by dartwork.
dartwork-mpl is a utility collection designed to elevate matplotlib visuals to publication-level elegance. Instead of wrapping matplotlib with a new API layer, it provides thin utilities that enhance matplotlib's native capabilities while keeping you in full control.
[!TIP] AI coding assistants: read
CLAUDE.md(orAGENTS.md) at the repo root for the 30-second onboarding. The link index follows the llmstxt.org spec atllms.txt; a single-file concatenated dump is atllms-full.txt.
[!IMPORTANT] Migrating from earlier dartwork-mpl? Both the 0.3 names (
dm.SW/MW/TW/DW,dm.FS_*,dm.WIDTHS,dm.cm2in,dm.agent_utils,dm.xplot) and the 0.4-era figure constructors (dm.subplots,dm.figure) have been removed. Each old access path now raisesAttributeError/ModuleNotFoundError/TypeErrorwith a message naming the new API. The canonical pattern isplt.subplots(figsize=dm.figsize("<n>cm", "<aspect>"))paired with a separatedm.style.use(...). Seedocs/migration.mdand the CHANGELOG for the full mapping.
Features
- Style Presets: Apply curated themes (
scientific,report,presentation) with one call. - Width × Aspect Geometry:
plt.subplots(figsize=dm.figsize("13cm", "standard"))— pick a physical width (cm/in/mm) and one of six aspect tokens (square / portrait / standard / golden / wide / cinema); height is derived. No more rawfigsize=(w, h)math. - Advanced Color System: Named color palettes (
oc.*,tw.*,md.*,ad.*,cu.*,pr.*) plus aColorclass supporting OKLab / OKLCH / RGB / hex color spaces with perceptual interpolation viacspace(). - Smart Layout:
simple_layout(fig)is a deterministic, content-aware margin pass that measures every visible artist and places the GridSpec arithmetically. Defaultmargin=0snaps content flush to figure edges;margin="2%"/dm.mm(2)adds a buffer. Replacestight_layout(). - Scaling Helpers: Relative font size (
fs), font weight (fw), and line width (lw) that respect the active style preset. - Icon Fonts: Built-in Material Design Icons (7,448+) and Font Awesome 6.
- Visual Validation: Automatic detection of overflow, text overlap, legend overflow, tick crowding, and empty axes via
validate_figure(). - Extended Plots: Ready-to-use plot templates like
plot_diverging_bar(). - Interactive Viewer: FastAPI-powered web UI (
dartwork_mpl.ui) for real-time parameter tuning. - Multi-format Export: Save figures in SVG, PNG, PDF, and EPS simultaneously.
- Prompt System: Bundled prompt guides for AI coding assistants, with
get_prompt()andcopy_prompt(). - MCP Server: AI coding assistant integration via Model Context Protocol (12 resources + 3 resource templates / 13 tools / 2 prompts).
- LLM Integration: Install usage guides for 9 AI tools (Claude Code, Cursor + MDC rules, GitHub Copilot, Codex CLI /
AGENTS.md, Gemini CLI / Antigravity, Continue, Aider, Windsurf) withinstall_llm_txt(targets="all").
Getting Started
Installation
Using uv (Recommended)
# Add to your project
uv add git+https://github.com/dartworklabs/dartwork-mpl
# Or install directly
uv pip install git+https://github.com/dartworklabs/dartwork-mpl
Using pip
pip install git+https://github.com/dartworklabs/dartwork-mpl
Quick Start
import matplotlib.pyplot as plt
import dartwork_mpl as dm
dm.style.use('scientific')
# Pick the physical width (cm/in/mm) and an aspect token. Height
# follows from aspect, so you never hand-tune figsize.
fig, ax = plt.subplots(figsize=dm.figsize('13cm', 'standard'))
ax.plot(x, y, color='oc.blue5', lw=dm.lw(0))
ax.set_xlabel('Time [s]')
dm.simple_layout(fig)
dm.save_formats(fig, 'output/figure', formats=('svg', 'png'))
dm.figsize(width, aspect) returns the inch tuple matplotlib's
figsize= expects. width accepts unit-suffixed strings ("13cm",
"6.7in", "170mm", "24pt") or Length values from the helper
calls (dm.cm(11.3), dm.inch(4.6), dm.mm(170), dm.pt(24));
the academic-column shortcuts dm.col1 (9 cm) and dm.col2 (17 cm)
work too. Bare int / float are rejected so the unit is always
explicit.
The second argument is polymorphic — pick whichever form reads naturally for the call site (the four forms are equivalent for fixed dimensions; the first matching form wins):
dm.figsize("13cm", "wide") # aspect token → 13 × 8.67 cm
dm.figsize("13cm", 0.6) # numeric ratio → 13 × 7.8 cm
dm.figsize("13cm", "8cm") # unit-string height
dm.figsize("13cm", dm.cm(8)) # Length height
dm.figsize("13cm", "5in") # mixed units (height in inches)
Aspect tokens are square / portrait / standard / golden / wide / cinema. Bare numeric strings ("0.5") are rejected with a
"drop the quotes" hint to keep the API unambiguous.
Core Modules
Style Management
Ready-to-use presets with style.use(), or stack individual styles for fine-grained control with style.stack().
dm.style.use('scientific') # apply preset
dm.style.stack(['base', 'font-scientific', 'lang-kr']) # stack custom
dm.list_styles() # list available .mplstyle files
dm.load_style_dict('font-presentation') # inspect style params
Color System
Named Colors
Importing dartwork_mpl registers palettes with oc.*, tw.*, md.*, ad.*, cu.*, pr.* prefixes:
ax.plot(x, y, color='oc.blue5') # Open Color
ax.bar(x, y, color='tw.emerald500') # Tailwind CSS
lighter = dm.mix_colors('oc.blue5', 'white', alpha=0.35)
muted = dm.pseudo_alpha('oc.blue7', alpha=0.6)
Color Class
The Color class provides perceptually uniform color manipulation across OKLab, OKLCH, RGB, and hex:
# Create from any color space
color = dm.oklch(0.7, 0.15, 150) # L, C, h (degrees)
color = dm.rgb(66, 133, 244) # auto-detects 0-255 range
color = dm.hex('#4285F4')
color = dm.named('oc.blue5')
# Read/write via views (mutable references)
color.oklch.C *= 1.2 # boost chroma
r, g, b = color.rgb # unpack RGB
# Perceptual interpolation
palette = dm.cspace('#FF0000', '#0000FF', n=5, space='oklch')
Layout & Annotation
dm.simple_layout(fig) # deterministic content-aware margin pass
dm.simple_layout(fig, margin="2%") # uniform 2% buffer; also dm.mm(2), dm.cm(0.5), "5mm"
dm.simple_layout(fig, gs=gs) # multi-panel: target a specific GridSpec
dm.label_axes(axes) # add (a), (b), (c) panel labels
dm.arrow_axis(ax, 'x', 'Cost') # Low ◄── Cost ──► High
dm.set_decimal(ax, xn=2, yn=1) # format tick decimals
offset = dm.make_offset(4, -4, fig) # point-based translation
Scaling Helpers
dm.fs(2) # base font size + 2pt
dm.fw(1) # base font weight + 100
dm.lw(-0.3) # base line width - 0.3
Length Helpers
dm.cm(13) # 13 cm → Length
dm.inch(4.6) # 4.6 in → Length
dm.mm(170) # 170 mm → Length
dm.pt(24) # 24 pt → Length (1 pt = 1/72 in)
dm.length('13cm') # parse a unit string → Length
dm.col1 # 9 cm — academic single-column sugar
dm.col2 # 17 cm — academic two-column sugar
# Multi-unit views (Color-style):
dm.cm(13).inch # 5.118
dm.cm(13).mm # 130.0
dm.cm(13).pt # 368.5
Migrating? Replace
figsize=(dm.cm2in(13), dm.cm2in(9.75))anddm.subplots(width="13cm", aspect="standard")withplt.subplots(figsize=dm.figsize("13cm", "standard")). The legacy aliases (SW / MW / TW / DW,FS_*,cm2in,agent_utils,xplot,dm.subplots,dm.figure) all raise at access time now.
Visual Validation
Automatic detection of rendering issues invisible in stdout-only environments (e.g., AI agent pipelines):
warnings = dm.validate_figure(fig)
# Checks: overflow, overlap, legend_overflow, tick_crowding, empty_axes
# Integrated into save_formats() by default
Icon Font System
mdi = dm.icon_font('mdi') # Material Design Icons
fa = dm.icon_font('fa-solid') # Font Awesome 6 Solid
ax.text(0.5, 0.5, "\U000F050F", fontproperties=mdi, fontsize=20)
dm.list_icon_fonts() # ['fa-brands', 'fa-regular', 'fa-solid', 'mdi']
File I/O & Prompts
dm.save_formats(fig, 'output/fig', formats=('png', 'svg', 'pdf'), dpi=300)
dm.save_and_show(fig, size=720) # save + inline preview
# Prompt guides for AI assistants
dm.list_prompts() # available guides
dm.get_prompt('00-index') # read the entry-point index (0.4 SSOT)
dm.copy_prompt('01-policy', '.cursor/rules/')
Extended Plots (templates)
Ready-to-use specialized visualization templates:
from dartwork_mpl.templates import plot_diverging_bar
fig, ax = plot_diverging_bar(
categories=['A', 'B', 'C'],
negatives=[-30, -15, -25],
positives=[40, 55, 35],
)
Interactive Viewer (UI)
FastAPI-powered web UI for real-time parameter tuning:
from dartwork_mpl.ui import ParamModel, run
from pydantic import Field
class Params(ParamModel):
n: int = Field(default=100, ge=10, le=1000)
alpha: float = Field(default=0.5, ge=0, le=1)
def my_plot(params: Params):
fig, ax = plt.subplots(figsize=dm.figsize("13cm", "standard"))
ax.scatter(range(params.n), np.random.randn(params.n), alpha=params.alpha)
return fig
run(my_plot) # opens browser at localhost:8501
LLM Integration
dm.install_llm_txt() # install usage guides to .claude/ and .cursor/
dm.uninstall_llm_txt() # remove installed guides
Available Presets
| Preset | Description |
|---|---|
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 |
All presets have a -kr Korean variant (e.g., scientific-kr, report-kr).
Documentation
📚 Full Documentation — Sphinx docs with:
- Installation — Setup guide
- Design Philosophy — Why thin utilities, not wrappers
- Usage Guide — Workflows and patterns
- Color System — Colors and colormaps reference
- API Reference — Function-level docs
- Example Gallery — Interactive examples
AI-Assisted Development (MCP Server)
dartwork-mpl ships a built-in Model Context Protocol (MCP) server so that AI coding assistants — Claude Code, Cursor, Windsurf, Antigravity — can pull the latest policy guides, color palettes, lint catalog, and helper tools straight into the chat context. No copy-pasting docs.
Install
# pip
pip install "dartwork-mpl[mcp]"
# uv
uv add "dartwork-mpl[mcp]"
The [mcp] extra installs fastmcp (>=2.13.3,<4) and httpx. After install, the
dartwork-mpl-mcp console script is on your PATH.
Claude Code
Add to ~/.claude.json (global) or <project>/.claude/mcp_servers.json:
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp"
}
}
}
Cursor
Add to ~/.cursor/mcp.json (global) or <project>/.cursor/mcp.json:
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp"
}
}
}
After saving, restart the client (or start a new conversation) and ask the assistant to list its MCP resources to confirm the server is reachable. For Windsurf, Antigravity (Gemini), generic stdio, troubleshooting, and the full resource/tool catalog, see docs/integrations/mcp_server.md (or the hosted version).
Working from a local clone instead of PyPI? Use
command: "uv"withargs: ["run", "--directory", "/abs/path/to/dartwork-mpl", "dartwork-mpl-mcp"]. The detailed docs cover this case.
Project Structure
src/dartwork_mpl/
├── __init__.py # Public API exports + lazy 0.3 alias shim
├── py.typed # PEP 561 type marker
├── units.py # cm/inch/mm, col1/col2, figsize, parse_width/parse_aspect
├── style.py # Style class + preset management
├── color/ # Color class (OKLab/OKLCH/RGB/hex) + palettes
├── layout.py # simple_layout(), label_axes()
├── annotation.py # arrow_axis(), label_axes()
├── scale.py # fs(), fw(), lw()
├── spines.py # hide_spines(), add_grid(), minimal_axes()
├── formatting.py # format_axis_*(), rotate_tick_labels()
├── io.py # save_formats(), save_and_show()
├── prompt.py # get_prompt(), copy_prompt(), list_prompts()
├── validate.py # validate_figure() — visual checks
├── validate_fixes.py # validate_with_fixes() — auto-fix helpers
├── lint.py # lint() against the anti-pattern catalog
├── diagnostics.py # plot_colormaps/plot_colors/plot_fonts
├── explore.py # list_palettes/list_colormaps/show_palette
├── icon.py # Icon font system (MDI, Font Awesome)
├── font.py # Font registration (lazy, locked)
├── cmap.py # Custom colormap registration (lazy, locked)
├── helpers/ # Stable helper utilities (data, labels, …)
├── templates/ # Extended plot templates (plot_diverging_bar)
├── install.py # LLM integration installer
├── cli.py # console-script entry (dartwork-mpl-mcp)
├── util.py # Legacy re-exports (deprecated cm2in, etc.)
├── constant.py # Deprecated 0.3 width constants (SW/MW/TW/DW)
├── ui/ # Interactive FastAPI viewer
├── mcp/ # MCP server for AI assistants
│ ├── server.py # FastMCP instance + wiring
│ ├── resources.py # 12 resources + 3 templates
│ ├── tools.py # 13 tools (color, lint+autofix, validate+render, migrate, info)
│ └── prompts.py # 2 prompts (create_plot, style_review)
└── asset/ # Bundled styles, colors, fonts, icons, prompts
Reporting Issues
Encountered a bug or have a feature request? Please open an issue through our GitHub issue tracker.
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
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 dartwork_mpl-0.4.1.tar.gz.
File metadata
- Download URL: dartwork_mpl-0.4.1.tar.gz
- Upload date:
- Size: 28.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2937c465875b4a7c33623b94e6f1db578f4303b735efc1532cfa01b229e8ab84
|
|
| MD5 |
cc13fc7b85a12a16e4ad5d28b891b7b0
|
|
| BLAKE2b-256 |
8692dea3ace9aa21a5fcf951619da16ef46cb9d1630866a44255c3cc4d2df9e6
|
File details
Details for the file dartwork_mpl-0.4.1-py3-none-any.whl.
File metadata
- Download URL: dartwork_mpl-0.4.1-py3-none-any.whl
- Upload date:
- Size: 28.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ab5f5a6c25e455ee7cbb3a2786e5e2498c53c66d7e790db75312a04851b1205
|
|
| MD5 |
ed2dc044ae3f5502c1b4495bece2a27b
|
|
| BLAKE2b-256 |
8fc45dbb7ae736b264f19d6726d4a9c39c59c18afceb8772902d0e6bbb0eddf5
|