Skip to main content

Small vector-first scientific plotting with clean publication-style defaults.

Project description

cleanfig

PyPI version Python versions License CI Release Gallery

cleanfig logo

Clean, opinionated, vector-first scientific plotting for Python. cleanfig is a small Rust/Python plotting package for clean scientific figures with vector-first export.

It is intentionally narrow: simple publication-style defaults, light visual clutter, compact labeling, and a small public API. The focus is on figures that should look close to final output without extensive styling code.

Useful links:

cleanfig four-panel dark example

Installation

Install from PyPI:

pip install cleanfig

Install the latest development GitHub version:

pip install git+https://github.com/adakite/cleanfig.git

Quick Start

import numpy as np
import cleanfig as cf

x = np.linspace(0, 10, 200)
y = np.sin(x)

fig = cf.figure(width="single", height=3.4, panel_labels=False)
ax = fig.panel(0, 0)
ax.line(x, y, label="signal")
ax.scatter(x[::20], y[::20], size=5)
ax.xlabel("x")
ax.ylabel("y")

fig.save("basic_line.svg")
fig.save("basic_line.html")
fig.save("basic_line.pdf")

Public API

The package is designed to be used as:

import cleanfig as cf

Current public entry points:

  • cf.figure(...)
  • Figure.panel(row, col)
  • Figure.save(path)
  • Panel.scatter(...)
  • Panel.line(...)
  • Panel.bar(...)
  • Panel.histogram(...)
  • Panel.field(...)
  • Panel.violin(...)
  • Panel.box(...)
  • Panel.colorbar(...)
  • Panel.legend()
  • Panel.xlabel(...)
  • Panel.ylabel(...)
  • Panel.right_ylabel(...)
  • Panel.xscale(...)
  • Panel.yscale(...)
  • Panel.limits(...)
  • Panel.right_limits(...)

API Reference

cf.figure(width="single", height=4.0, grid=(1, 1), panel_labels=False, font=None, theme="publication")

  • width: "single" or "double"
  • height: figure height in inches
  • grid: (rows, cols)
  • panel_labels: add panel letters
  • font: custom font family string
  • theme: "publication" / "nature" / "light" alias, or "dark"

Axis labels, limits, and scales

  • ax.xlabel(label)
  • ax.ylabel(label)
  • ax.right_ylabel(label): label for a secondary right Y axis
  • ax.limits(x=None, y=None): explicit limits for the main X/Y axes
  • ax.right_limits(y=None): explicit limits for the right Y axis
  • ax.xscale("linear" | "log")
  • ax.yscale("linear" | "log", axis="left" | "right")

Log scales require strictly positive values and strictly positive limits.

ax.scatter(x, y, color=None, size=6.0, alpha=0.8, label=None, cmap=None, yaxis="left")

  • x, y: same-length numeric arrays
  • color: named/hex color or numeric array for colormap mapping
  • size: marker diameter in points
  • alpha: opacity
  • label: legend entry
  • cmap: colormap name for mapped colors; see Built-in Colormaps below
  • yaxis: "left" or "right" for dual-Y figures

Returns a PlotHandle when color mapping is used.

ax.line(x, y, color=None, width=1.2, alpha=1.0, label=None, yaxis="left")

  • color: named/hex color
  • width: stroke width in points
  • alpha: opacity
  • label: legend entry
  • yaxis: "left" or "right"

ax.bar(labels, values, yaxis="left", color=None, alpha=1.0, show_x_axis=False)

  • labels: categorical X labels
  • values: numeric heights
  • yaxis: "left" or "right"
  • color: named/hex color
  • alpha: opacity
  • show_x_axis: draw the bottom X axis line and ticks for bar charts

ax.histogram(data, bins=12, range=None, density=False, color=None, alpha=1.0, label=None, yaxis="left")

  • data: numeric samples
  • bins: number of bins
  • range: optional (min, max) binning range
  • density: normalize to probability density instead of counts
  • color: named/hex fill color
  • alpha: opacity
  • label: legend entry
  • yaxis: "left" or "right"

ax.field(grid, cmap=None, cell_edges=False, render="auto")

  • grid: 2D numeric array
  • cmap: colormap name; see Built-in Colormaps below
  • cell_edges: draw subtle cell borders when True
  • render: "auto", "grid", or "embedded"

render="auto" is the default. In the Rust backend, dense fields automatically switch to an embedded raster image to avoid visible seams between cells, while smaller fields remain grid/vector based. Use "grid" to force cell-by-cell rendering or "embedded" to force the rasterized field image path.

Returns a PlotHandle for optional colorbar creation.

ax.colorbar(handle, label=None, placement=None, style=None)

  • handle: result of a mapped scatter, field, or mapped-point violin
  • label: colorbar label
  • placement: "right" or "inside-left"
  • style: "binned" or "continuous"

Current default is "binned".

ax.violin(data, labels=None, show_median=False, points=False, point_color=None, point_size=4.0, point_alpha=0.75, point_cmap=None)

  • data: grouped numeric data
  • labels: category labels
  • show_median: draw median segment
  • points: overlay individual points
  • point_color: constant color, flat array, or grouped arrays
  • point_size: point diameter
  • point_alpha: point opacity
  • point_cmap: colormap for mapped points; see Built-in Colormaps below

Returns a PlotHandle when mapped point colors are used.

ax.box(data, labels=None)

  • data: grouped numeric data
  • labels: category labels

ax.legend()

Creates a compact frameless legend from labeled layers.

Current Feature Status

  • Supported: line, scatter, bar, histogram, violin, box, field plots with auto grid/embedded rendering
  • Supported: light/dark themes, log X/Y axes, dual Y axes, SVG/HTML/PDF export
  • Not supported yet: ax.spectrogram(), logarithmic colorbars, geographic projections

Examples

Useful example scripts are provided in examples/:

  • basic_line.py
  • four_panels.py
  • violin_box_light.py
  • esec_dual_y_light.py for a light-theme dual-Y example using a pandas.DataFrame loaded from a bundled ESEC catalog extract in examples/Data/
  • theme-specific wrappers for light/dark example output

Export Formats

Supported export targets:

  • SVG
  • HTML with embedded SVG
  • PDF through SVG conversion in the Rust backend

Built-in Colormaps

cleanfig currently ships with a larger built-in continuous colormap set.

General:

  • gray
  • magma
  • bone

Fabio Crameri family currently integrated:

  • Sequential-ish: acton, bamako, batlow, bilbao, devon, hawaii, imola, lajolla, lapaz, lipari, navia, nuuk, oslo, tokyo, turku
  • Diverging / balanced: berlin, broc, cork, managua, roma, tofino, vanimo, vik

Notes:

  • These Crameri maps were integrated as built-in names so the plotting API stays unchanged: cmap="roma", cmap="batlow", etc.
  • Unknown colormap names still fall back to batlow.
  • Colormap attribution and licensing notice: LICENSE-THIRD-PARTY.md

Citation for the integrated Scientific colour maps:

Crameri, F. (2023). Scientific colour maps (8.0.1). Zenodo. https://doi.org/10.5281/zenodo.8409685

Design Philosophy

  • vector-first output
  • clean left/bottom axes by default
  • minimal plot constructors
  • no GUI, dashboards, or heavyweight plotting state
  • useful scientific defaults over maximum flexibility

Fallback Behavior

cleanfig prefers the compiled Rust extension.

If the extension is unavailable, it falls back to a pure Python implementation. The fallback is intended for graceful local use and testing, but it is not feature-complete. In particular, PDF export is only available when the Rust backend is loaded.

You can inspect the active backend with:

import cleanfig as cf
print(cf.BACKEND)

Current Limitations

  • no ax.spectrogram() yet
  • no logarithmic colorbars
  • no standalone raster plotting backend beyond embedded dense field rendering
  • no geographic projections
  • visual styling is intentionally constrained
  • the Python fallback keeps field rendering grid-based even when render="embedded" is requested

Development Install

python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"
maturin develop
pytest -q

The esec_dual_y_light.py example additionally expects pandas, which is included in the dev extra. The bundled ESEC source file and citation notes are stored under examples/Data/.

Citation, License, Contact

  • License: MIT, see LICENSE
  • Changelog: CHANGELOG.md
  • Release checklist: RELEASE.md
  • Contact: Antoine Lucas

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

cleanfig-1.1.4.tar.gz (223.5 kB view details)

Uploaded Source

Built Distributions

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

cleanfig-1.1.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

cleanfig-1.1.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (4.0 MB view details)

Uploaded CPython 3.10+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file cleanfig-1.1.4.tar.gz.

File metadata

  • Download URL: cleanfig-1.1.4.tar.gz
  • Upload date:
  • Size: 223.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cleanfig-1.1.4.tar.gz
Algorithm Hash digest
SHA256 ea5a43b0d48fa358fa01cb461598d83f2e3568b2dcd246b0d3dd8115e5b88386
MD5 0f5d494decbf82c19d0febedabdbfe47
BLAKE2b-256 618f01745e22616a7a61985b2a222f2f2afd5de05fffc8e25b8c68ca66b8a19f

See more details on using hashes here.

Provenance

The following attestation bundles were made for cleanfig-1.1.4.tar.gz:

Publisher: release.yml on adakite/cleanfig

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

File details

Details for the file cleanfig-1.1.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cleanfig-1.1.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4ae050aeb6d2aa3e252d298ebe44703fb1b7a65b36dc07a45887d83f6957b8d3
MD5 7df34f40a862844b1a3bb01c5db31b85
BLAKE2b-256 54e77cade23f1ffe70a5e59632d96088cee7d4933ba0bfe88841a367298e4111

See more details on using hashes here.

Provenance

The following attestation bundles were made for cleanfig-1.1.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on adakite/cleanfig

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

File details

Details for the file cleanfig-1.1.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for cleanfig-1.1.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 05221faca1ec212549a67efbee001a90b235ee552a616b7869b1b6334482791c
MD5 1b93e7312668bbb450c33f3e4bad3768
BLAKE2b-256 fbd2f3443933a26e5ee16e971ea66decb8c2ba388224098a028f1779c0b1dfc9

See more details on using hashes here.

Provenance

The following attestation bundles were made for cleanfig-1.1.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: release.yml on adakite/cleanfig

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