Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 1.1.4 instead.

Onsaemiro

Publication-quality matplotlib styling for Academic Research.

Onsaemiro provides a streamlined interface for generating figures that meet the rigorous standards of scientific journals. It handles font scaling, consistent subplot positioning, colour-blind friendly palettes, and GitHub-safe progress bars — all with minimal boilerplate.


Key Features

  • Flexible Scientific Layouts: Supports fixed single axes, subplot grids, GridSpec ratios, and Matplotlib constrained layout.
  • Automatic Scaling: Adjusts font sizes, line widths, and tick marks based on the physical figure width.
  • Journal Presets: Practical single- and double-column starting points for Nature, Science, IEEE, and APS figures.
  • Academic Palettes: Built-in support for Okabe-Ito, Paul Tol (Vibrant, Muted, Bright), and IBM palettes.
  • TableMaker: Renders LaTeX-style "booktabs" tables directly in Jupyter notebooks or the terminal.
  • ProgressBar / track(): Static-HTML progress bar that survives GitHub's notebook renderer — no ipywidgets required.
  • Context Management: Use fixed_frame for one-off figures with specific dimensions without affecting global settings.

Installation

Install Onsaemiro from PyPI:

pip install onsaemiro

The package is published on PyPI and can also be installed directly from a local clone.

For local development, clone the repository, move into the package directory, and run:

pip install -e .

The -e (editable) flag means changes to the Onsaemiro source are reflected immediately — no reinstall needed.

Additional guidance:


Quick Start

import onsaemiro as osm
import matplotlib.pyplot as plt
import numpy as np

# 1. Global setup
osm.set_style(figure_size=(3.5, 2.5), palette="okabe-ito")

# 2. Get the palette
colors = osm.get_palette()

# 3. Plotting
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()

ax.plot(x, np.sin(x), color=colors['blue'], label='Signal A')
ax.plot(x, np.cos(x), color=colors['orange'], label='Signal B')

ax.set_xlabel('Time (s)')
ax.set_ylabel('Amplitude (V)')
ax.legend()

# 4. Finalise (handles legend borders and origin overlaps)
osm.finalize(ax)
plt.show()

Core Components

1. Global Styling (set_style)

Configures plt.rcParams for publication. Unlike standard matplotlib behaviour, it disables autolayout to ensure that labels do not shift the axes box. Defaults to a Times-style serif font.

osm.set_style(
    base_fontsize=12.5,
    linewidth=1.2,
    figure_size=(3.5, 2.5),
    use_tex=False
)

2. Colour Palettes (Palette)

Access colours by name or index. Supports fuzzy name matching.

  • okabe-ito (Default, colour-blind safe)
  • paul-tol-vibrant | paul-tol-bright | paul-tol-muted
  • ibm
  • tableau10
p = osm.get_palette("vibrant")
color = p['red']    # Name access
color = p[0]        # Index access (wraps around)

3. Layout Control (fixed_frame)

A context manager for creating figures with precise axes placement.

with osm.fixed_frame(figure_size=(5, 4)) as (fig, ax):
    ax.scatter(data_x, data_y)
    # Axes position is determined by internal fractions,
    # ensuring consistent whitespace across different plots.

The original single-axis API is unchanged. Multiple panels and GridSpec ratios are available through optional arguments:

with osm.fixed_frame(
    figure_size=(7.2, 4.8),
    nrows=2,
    ncols=2,
    gridspec_kw={"width_ratios": [2, 1]},
) as (fig, axes):
    axes[0, 0].plot(x, y)

Use layout="constrained" when Matplotlib should manage spacing instead of Onsaemiro's fixed subplot fractions.

4. Journal presets and export

Journal presets are reproducible starting points, not substitutes for checking the current author instructions:

osm.set_journal_style("nature", column="single")

fig, ax = plt.subplots()
ax.plot(x, y)

osm.export_figure(fig, "figures/result.pdf")
osm.export_figure(fig, "figures/result.svg")

export_figure() creates parent directories, embeds TrueType fonts in PDF/PS, and returns the output path.

5. TableMaker

Creates professional tables for results analysis. In Jupyter, renders a monochrome theme inspired by academic journals (booktabs style). In terminals, renders via rich.

table = osm.TableMaker(
    title="Performance Metrics",
    columns=["Metric", "Result", "Unit"]
)
table.add_row("R-Squared", "0.9942", "—")
table.add_row("RMSE", "0.021", "m/s")
table.display()

Tables can validate and format values, sort rows, and export CSV or booktabs LaTeX:

table = osm.TableMaker(
    columns=["Case", "RMSE"],
    formatters={"RMSE": ".3f"},
)
table.add_row("baseline", 0.01234)
table.sort("Case")
table.to_csv("results/metrics.csv")
latex = table.to_latex(caption="Model error", label="tab:error")

For live updates during a loop (e.g. training), use mode="live":

table = osm.TableMaker(title="Training Log", columns=["Epoch", "Loss"], mode="live")
for epoch in range(10):
    loss = train_one_epoch()
    table.add_row(str(epoch), f"{loss:.4f}")

6. ProgressBar and track()

A static-HTML progress bar designed for Jupyter notebooks. Unlike tqdm.auto, it renders as plain text/html output — so the completed bar is preserved when notebooks are committed to GitHub, rather than showing an empty widget placeholder.

Simple iterator (tqdm-style)

for x in osm.track(range(1000), desc="Training"):
    osm.sleep(0.001)

Context manager (manual update)

Use this when the loop body controls iteration (e.g. custom data loaders).

with osm.ProgressBar(total=N, desc="Sweep") as pb:
    for i in range(N):
        compute(i)
        pb.update()

Joblib parallel jobs

When using joblib.Parallel, pass return_as="generator" and wrap with osm.track(). Results are yielded as each job completes, so the progress bar advances in real time.

from joblib import Parallel, delayed

def process(i):
    osm.sleep(0.05)   # simulate work
    return i ** 2

results = list(
    osm.track(
        Parallel(n_jobs=-1, return_as="generator")(
            delayed(process)(i) for i in range(100)
        ),
        total=100,
        desc="Parallel",
    )
)

Note: return_as="generator" requires joblib ≥ 1.2. The progress bar advances as jobs complete, not as they are dispatched — so the count accurately reflects finished work.

Key parameters

Parameter Default Description
iterable None Wrap any iterable for iterator-style use
total len(iterable) Total iterations (required when iterable has no len)
desc "" Prefix label shown before the bar
mininterval 0.1 s Minimum time between HTML refreshes — prevents rendering from bottlenecking tight loops
smoothing 0.3 Exponential smoothing applied to rate and ETA estimates
width 40 Bar width in characters (terminal mode only)

Any iterable can be wrapped, including generators returned by concurrent.futures, Dask, or joblib. Supply total= when the iterable has no length. Onsaemiro does not require those frameworks as dependencies.

7. Custom palettes

osm.register_palette(
    "laboratory",
    {"cold": "#2468A2", "hot": "#D1495B"},
)
osm.save_palette("laboratory", "palettes/laboratory.json")
osm.load_palette("palettes/laboratory.json", overwrite=True)

API Reference

Function / Class Description
set_style(...) Initialises global matplotlib parameters.
reset_style() Restores matplotlib defaults.
get_palette(name) Returns a Palette object with fuzzy name matching.
build_color_map(labels) Maps a list of unique labels to palette colours.
register_palette(...) Registers a custom named palette.
save_palette(...) / load_palette(...) Persists custom palettes as JSON.
finalize(ax) Polishes the plot: legend frames, origin overlaps, optional grid/minor ticks.
fixed_frame(...) Context manager for isolated figure styling with fixed axes placement.
journal_preset(...) / set_journal_style(...) Reads or applies a journal-oriented preset.
export_figure(...) Exports PNG/PDF/SVG and other Matplotlib formats safely.
annotate_panels(axes) Automatically adds (a), (b), (c) labels to subplots.
style_colorbar(cb) Applies publication styling to a colorbar.
enable_minor_ticks(ax) Adds AutoMinorLocator ticks to both axes.
apply_grid(ax) Adds a subtle dotted grid.
TableMaker(...) Renders academic-style tables in the console or Jupyter.
ProgressBar(...) Static-HTML progress bar; GitHub-safe in Jupyter.
track(iterable) tqdm-style shorthand for ProgressBar.
sleep(s) Re-export of time.sleep — avoids a separate import in notebooks.
info() Prints version and dependency information.

Version History

  • v1.0.5 (18 Aug 2026): Restored fixed_frame, added multi-panel layouts, journal presets, safe export, custom palettes, table export, and expanded validation and tests.
  • v1.0.4 (18 Aug 2026): Improved live terminal table rendering and idempotent final output.
  • v1.0.3 (13 Aug 2026): Added terminal/Jupyter tables and static progress reporting used by FoamNordic workflows.
  • v1.0.1 (10 Aug 2026): Refactored the internal package structure while preserving the public API.
  • v1.0.0 (24 Jul 2026): Initial Onsaemiro release, based on the final DataGraph 3.1.0 implementation.

Created and maintained by Hanseul Kang.

Metadata

Release files for onsaemiro 1.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for onsaemiro 1.0.5
File Size Uploaded
onsaemiro-1.0.5.tar.gz 27.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for onsaemiro 1.0.5
File Interpreter ABI Platform
onsaemiro-1.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 49.6 kB

Release files / onsaemiro-1.0.5.tar.gz

Download URL onsaemiro-1.0.5.tar.gz
Size 27.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b117a4561d9f34d7a026dd8d84fca024ba988fbdd1887f7e09ebfd862a5c3852
BLAKE2b-256 checksum
How to use checksums
8c0d370049cc15317974f81fcf32069092ea639fe63af5cc89f7e414273654e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / onsaemiro-1.0.5-py3-none-any.whl

Download URL onsaemiro-1.0.5-py3-none-any.whl
Size 22.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
448379a8b8f606a220d2cc01862b94499a0666f18e2b76ff408ac81147404003
BLAKE2b-256 checksum
How to use checksums
66b5ec61fff0af09c32ac327d2720b4e6013dbb8ef9f178806e886a5fcd2264b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page