Skip to main content

A next-gen Python plotting library with SVG-first rendering, interactivity, themes, and clean defaults

Project description

GlyphX

A next-generation Python visualization library — SVG-first, interactive, and built to replace Matplotlib, Seaborn, and Plotly.

CI Documentation PyPI Release License: MIT Python 3.12+

GlyphX renders crisp, interactive SVG charts that work everywhere — Jupyter notebooks, CLI pipelines, FastAPI servers, and static HTML files — with zero configuration and no plt.show() required.


Why GlyphX?

Feature GlyphX Matplotlib Seaborn Plotly
Auto-display (no show())
Method chaining API Partial
DataFrame accessor (df.glyphx.*) Partial
Natural language chart generation
Linked interactive brushing ✅ (needs server)
Self-contained shareable HTML
Statistical significance brackets
ECDF plot
Raincloud plot
3-D scatter / surface / line / bar ✅ (WebGL + SVG) ✅ (WebGL)
Bubble chart
Sunburst chart
Parallel coordinates
Diverging bar
Auto large-data downsampling (SVG) ✅ M4+LTTB+voxel Rasterises
Perceptually-uniform colormaps ✅ (9 built-in)
Continuous color encoding (scatter)
Candlestick / OHLC
Waterfall / bridge chart
Treemap (squarified)
Streaming / real-time series ✅ (no server) ✅ (needs server)
Synchronized crosshair ✅ (needs server)
PPTX export
CLI tool (glyphx plot data.csv)
Full ARIA / WCAG 2.1 AA accessibility Partial
Full type annotations (py.typed) Partial
tight_layout() ✅ auto Manual Auto Auto
Log-scale axes
Dual Y-axis
Error bars (X and Y)

Installation

pip install glyphx

# Optional extras
pip install "glyphx[export]"  # PNG/JPG raster export   (cairosvg)
pip install "glyphx[pptx]"    # PowerPoint export        (python-pptx + cairosvg)
pip install "glyphx[nlp]"     # Natural language charts  (anthropic)
pip install "glyphx[all]"     # Everything

Requirements: Python 3.12+ · NumPy ≥ 1.26 · pandas ≥ 2.1


Quick Start

from glyphx import plot

# One-liner — auto-displays in Jupyter, opens browser in CLI
plot([1, 2, 3], [4, 5, 6], kind="line", title="My First Chart")
from glyphx import Figure
from glyphx.series import LineSeries, BarSeries

months  = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
revenue = [120, 145, 132, 178, 159, 203]
costs   = [ 80,  90,  85, 105,  98, 115]

fig = (
    Figure(width=800, height=500)
    .set_title("Revenue vs Costs — H1")
    .set_theme("dark")
    .set_xlabel("Month")
    .set_ylabel("USD (thousands)")
    .add(LineSeries(months, revenue, color="#60a5fa", label="Revenue"))
    .add(LineSeries(months, costs,   color="#f87171", label="Costs", linestyle="dashed"))
    .add_stat_annotation("Jan", "Jun", p_value=0.004)
    .set_legend("top-left")
    .tight_layout()
)

fig.show()                     # Jupyter inline or browser tab
fig.save("chart.svg")          # SVG vector
fig.save("chart.html")         # Interactive HTML
fig.save("chart.png")          # Raster PNG  (requires cairosvg)
fig.save("chart.pptx")         # PowerPoint  (requires glyphx[pptx])
fig.share("report.html")       # Zero-CDN self-contained HTML

Core APIs

plot() — One-liner charts

The fastest path to any chart type. Mirrors pandas' df.plot():

from glyphx import plot

plot([1,2,3], [4,5,6],          kind="line",    title="Line")
plot(["A","B","C"], [10,20,15], kind="bar",     title="Bar")
plot([1,2,3], [4,5,6],          kind="scatter", title="Scatter")
plot(data=[30, 40, 30],          kind="pie",     labels=["A","B","C"])
plot(data=[30, 40, 30],          kind="donut",   labels=["A","B","C"])
plot(data=raw_values,            kind="hist",    bins=20)
plot(data=raw_values,            kind="box")
plot(data=matrix,                kind="heatmap")

Method-Chaining API

Every method returns self. Build the entire chart in one expression:

fig = (
    Figure(width=900, height=520, theme="warm")
    .set_title("Q3 Performance")
    .set_xlabel("Month").set_ylabel("Revenue ($M)")
    .set_legend("bottom-right")
    .add(LineSeries(x, revenue, label="Revenue"))
    .add(BarSeries(x, costs,   label="Costs"), use_y2=True)
    .annotate("Record High", x=10, y=5.4, arrow=True, color="#dc2626")
    .add_stat_annotation("Jan", "Jun", p_value=0.001)
    .vline(x=6, color="#888", linestyle="dashed")
    .hline(y=5.0, color="#888", linestyle="dotted")
    .tight_layout()
    .share("dashboard.html")
)

DataFrame Accessor

Import glyphx once — every pd.DataFrame gains .glyphx:

import pandas as pd
import glyphx           # registers accessor automatically

df = pd.read_csv("sales.csv")

# One-liner charts from column names
df.glyphx.line(x="date",     y="revenue", title="Daily Revenue")
df.glyphx.bar( x="product",  y="sales",   title="Sales by Product")
df.glyphx.scatter(x="spend", y="revenue")
df.glyphx.hist(col="response_time", bins=20)
df.glyphx.box(col="score", groupby="region")
df.glyphx.pie(labels="category",  values="share")
df.glyphx.donut(labels="segment", values="revenue")
df.glyphx.heatmap(title="Correlation Matrix")

# Groupby aggregation
df.glyphx.bar(groupby="region", y="revenue", agg="sum",
              title="Revenue by Region")

# Hue splitting — one BarSeries per unique region value, auto-colored
df.glyphx.bar(x="month", y="revenue", hue="region",
              title="Revenue by Month and Region")

# Full chain from the accessor
(df.glyphx
   .bar(x="month", y="revenue", auto_display=False)
   .set_theme("dark")
   .add_stat_annotation("Jan", "Jun", p_value=0.002)
   .share("report.html"))

Natural Language Charts

Describe a chart in plain English; GlyphX builds it.
Requires pip install "glyphx[nlp]" and ANTHROPIC_API_KEY.

from glyphx import from_prompt
import pandas as pd

df = pd.read_csv("sales.csv")

# GlyphX infers chart type, axis mapping, grouping, theme, and title
fig = from_prompt("bar chart of total revenue by region, dark theme", df=df)

# Without a DataFrame — generates illustrative sample data
fig = from_prompt("scatter plot showing a strong positive correlation")

# Complex intent
fig = from_prompt(
    "top 10 products by revenue this quarter, sorted descending",
    df=df,
)

Chart Types

Core charts

from glyphx.series import (
    LineSeries, BarSeries, ScatterSeries,
    PieSeries, DonutSeries, HistogramSeries,
    BoxPlotSeries, HeatmapSeries,
)

# Line — multiple linestyles, error bars
LineSeries(x, y,
    color="#2563eb",  label="Revenue",
    linestyle="dashed",          # solid | dashed | dotted | longdash | step
    width=2,
    yerr=error_values,           # symmetric Y error bars with caps
    xerr=x_error_values,         # symmetric X error bars
)

# Bar — error bars, per-bar color list
BarSeries(x, y,
    color="#7c3aed",  label="Units",
    bar_width=0.7,
    yerr=std_errors,
)

# Scatter — continuous color encoding
ScatterSeries(x, y,
    c=z_values,                  # per-point values → colormap
    cmap="viridis",              # any of 9 built-in colormaps
    size=6,
    marker="circle",             # circle | square
)

# Histogram
HistogramSeries(data, bins=20, color="#0891b2")

# Box plot — single or multi-group
BoxPlotSeries([group_a, group_b, group_c],
    categories=["Control", "Drug A", "Drug B"],
    box_width=24,
)

# Heatmap — colorbar, row/col labels, value overlay
HeatmapSeries(matrix,
    row_labels=row_names,
    col_labels=col_names,
    show_values=True,
    cmap=["#1e40af", "#f0f0f0", "#b91c1c"],  # custom diverging
)

Statistical

# ECDF — no bin-width choice needed, shows full distribution
from glyphx.ecdf import ECDFSeries
fig.add(ECDFSeries(data, label="Control",  complementary=False))
fig.add(ECDFSeries(data2, label="Treatment"))

# KDE — smooth density curve (no scipy required)
from glyphx.kde import KDESeries
fig.add(KDESeries(data, filled=True, alpha=0.20, label="Density"))

# Area / fill-between
from glyphx.fill_between import FillBetweenSeries
fig.add(FillBetweenSeries(x, y_lower, y_upper, color="#2563eb", alpha=0.25,
                          label="95% CI"))

# Raincloud — jitter + half-violin + box in one plot
from glyphx.raincloud import RaincloudSeries
fig.add(RaincloudSeries(
    data=[control, drug_a, drug_b],
    categories=["Control", "Drug A", "Drug B"],
    violin_width=35,
))

# Violin plot
from glyphx.violin_plot import ViolinPlotSeries
fig.add(ViolinPlotSeries([grp_a, grp_b], show_median=True, show_box=True))

# Statistical significance brackets (built-in, no extra package)
fig.add_stat_annotation("Control", "Drug A", p_value=0.001)          # → ***
fig.add_stat_annotation("Control", "Drug B", p_value=0.031, y_offset=30)  # stack
fig.add_stat_annotation("Drug A",  "Drug B", p_value=0.18,  style="numeric")

Financial

# Candlestick / OHLC
from glyphx.candlestick import CandlestickSeries
fig.add(CandlestickSeries(
    dates=["Mon", "Tue", "Wed", "Thu", "Fri"],
    open= [150, 153, 149, 155, 158],
    high= [155, 157, 153, 160, 162],
    low=  [148, 151, 146, 154, 156],
    close=[153, 149, 155, 158, 160],
))

# Waterfall / bridge chart
from glyphx.waterfall import WaterfallSeries
fig.add(WaterfallSeries(
    labels=["Q2 Revenue", "New Sales", "Upsell", "Churn", "Q3 Revenue"],
    values=[8_200_000, 2_100_000, 650_000, -420_000, None],  # None = auto-total
    show_values=True,
))

Hierarchical

# Treemap — squarified layout, area-proportional rectangles
from glyphx.treemap import TreemapSeries
fig.add(TreemapSeries(
    labels=["Cloud", "AI", "Mobile", "Security", "Data"],
    values=[4200,    3100, 2800,     2100,        1900],
    cmap="viridis",
    show_values=True,
))

3-D Charts

Use Figure3D for interactive Three.js WebGL output with an SVG fallback. All 3-D series support per-series threshold= and expose last_downsample_info after rendering.

from glyphx import Figure3D, plot3d
from glyphx.scatter3d import Scatter3DSeries
from glyphx.surface3d  import Surface3DSeries
from glyphx.line3d     import Line3DSeries
from glyphx.bar3d      import Bar3DSeries
from glyphx.contour    import ContourSeries
import numpy as np

# 3-D scatter with colormap
fig = Figure3D(title="Clusters", theme="dark", azimuth=45, elevation=30)
fig.add(Scatter3DSeries(xs, ys, zs, c=zs, cmap="plasma", size=4))
fig.show()   # WebGL interactive; .save("chart.html") for sharing

# 3-D surface — auto-decimated for large grids
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
Z = np.sin(np.sqrt(x[None,:]**2 + y[:,None]**2))
Figure3D().add(Surface3DSeries(x, y, Z, cmap="viridis", wireframe=True)).show()

# Helix polyline
t = np.linspace(0, 4*np.pi, 2000)
Figure3D().add(Line3DSeries(np.cos(t), np.sin(t), t/(4*np.pi))).show()

# One-liner
plot3d(xs, ys, zs, kind="scatter", title="Quick 3D")
plot3d(x, y, Z,   kind="surface", title="Quick Surface")

New Chart Types (v1.5+)

# Bubble — scatter with size encoding
from glyphx.bubble import BubbleSeries
fig.add(BubbleSeries(x, y, sizes=market_cap, c=growth, cmap="plasma"))

# Sunburst — multi-ring hierarchy
from glyphx.sunburst import SunburstSeries
fig.add(SunburstSeries(labels=[...], parents=[...], values=[...]))

# Parallel coordinates
from glyphx.parallel_coords import ParallelCoordinatesSeries
fig.add(ParallelCoordinatesSeries(data=df[cols], labels=df["species"]))

# Diverging bar
from glyphx.diverging_bar import DivergingBarSeries
fig.add(DivergingBarSeries(categories=[...], values=[12,-8,21,-3]))

Streaming / Real-Time

from glyphx.streaming import StreamingSeries

fig    = Figure(title="Live Sensor Feed")
stream = StreamingSeries(max_points=100, color="#7c3aed", label="Sensor")
fig.add(stream)

# Manual push
stream.push(42.0)
stream.push_many([41.5, 42.3, 43.1])

# Jupyter live mode — re-renders at target FPS, no server needed
with stream.live(fig, fps=10) as s:
    for reading in sensor_generator():
        s.push(reading)

Large-Data Downsampling

GlyphX automatically keeps SVG files fast on large datasets. All algorithms are fully vectorised with NumPy.

Series type Algorithm Threshold
LineSeries Two-stage M4 → LTTB M4 at 50k pts; LTTB at 5k pts
ScatterSeries 2-D voxel grid thinning 5k pts
Line3DSeries LTTB in screen space (camera-aware) 5k pts
Scatter3DSeries 3-D voxel grid thinning 5k pts
Surface3DSeries Grid decimation + face culling 5k faces
# Per-series threshold override
from glyphx.series import LineSeries
ls = LineSeries(x, y, threshold=1_000)   # keep at most 1 000 points

# Inspect what happened after render
ls_info = ls.last_downsample_info
# {'algorithm': 'M4+LTTB', 'original_n': 200000, 'thinned_n': 1000}

# Global kill-switch (thread-local — safe for multi-threaded renderers)
import glyphx.downsample as ds
ds.disable()   # no downsampling on this thread
fig.render_svg()
ds.enable()

# Manual use of any algorithm
from glyphx.downsample import lttb, m4, voxel_thin_2d, lttb_3d, decimate_grid
x_down, y_down = lttb(x, y, threshold=2_000)
x_m4,   y_m4   = m4(x, y, pixel_width=800)
xt, yt, ct     = voxel_thin_2d(xs, ys, c=labels, max_points=5_000)

See the Downsampling docs for the full API, benchmark results, and the test suite.


Interactivity

All charts rendered to HTML include:

Interaction How
Tooltips Hover any data point
Zoom Mouse wheel
Pan Click and drag
Reset zoom Double-click
Linked brushing Shift + drag — filters all charts on the page
Keyboard navigation Tab / Arrow keys between data points
Legend toggle Click a legend item to show/hide its series
Export SVG / PNG buttons in the toolbar
Synchronized crosshair fig.enable_crosshair()

Linked Brushing

Hold Shift and drag a selection rectangle on any chart. All charts on the page with matching X values highlight together and dim non-matching points. Press Escape to clear.

from glyphx.layout import grid

f1 = Figure(auto_display=False).add(ScatterSeries(x, y1, label="Sales"))
f2 = Figure(auto_display=False).add(LineSeries(x, y2, label="Revenue"))

html = grid([f1, f2], rows=1, cols=2)
open("dashboard.html", "w").write(html)

Advanced Layout

# Dual Y-axis
fig.add(LineSeries(x, prices, label="Price (left)"))
fig.add(BarSeries(x, volume, label="Volume (right)"), use_y2=True)

# Log-scale axes
fig = Figure(yscale="log")
fig = Figure(xscale="log", yscale="log")

# Subplot grid
fig = Figure(rows=2, cols=2, width=1000, height=700)
ax0 = fig.add_axes(0, 0);  ax0.add_series(LineSeries(x, y))
ax1 = fig.add_axes(0, 1);  ax1.add_series(BarSeries(cats, vals))
ax2 = fig.add_axes(1, 0);  ax2.add_series(ScatterSeries(x, y2))
ax3 = fig.add_axes(1, 1);  ax3.add_series(HistogramSeries(data))

# Reference lines
fig.vline(x=50,  color="#e11d48", linestyle="dashed")
fig.hline(y=3.5, color="#0284c7", linestyle="dotted")

# Text annotations with optional arrows
fig.annotate("Peak", x=10, y=5.4, arrow=True, color="#dc2626", font_size=12)
fig.annotate("Baseline", x=0, y=2.0, anchor="start")

# Auto tight layout (adjusts padding, rotates crowded X labels)
fig.tight_layout()

Colormaps

Nine perceptually-uniform colormaps:

Name Type Best for
viridis Sequential Default continuous encoding
plasma Sequential High-contrast continuous
inferno Sequential Print-safe dark backgrounds
magma Sequential Heatmaps and density
cividis Sequential Deuteranopia-safe
coolwarm Diverging Correlation matrices
rdbu Diverging Positive / negative values
spectral Multi-hue Categorical ranges
greys Sequential Monochrome / print export
from glyphx.colormaps import apply_colormap, colormap_colors, list_colormaps

apply_colormap(0.75, "plasma")      # → "#eb5f34"
colormap_colors("viridis", 6)       # → list of 6 hex colors
list_colormaps()                    # → ["cividis", "coolwarm", ...]

# Color-encode scatter by a third variable
ScatterSeries(x, y, c=z_values, cmap="inferno")

Themes

Seven built-in themes:

Figure(theme="default")      # clean white background
Figure(theme="dark")         # charcoal background
Figure(theme="colorblind")   # Okabe-Ito palette — safe for all color vision types
Figure(theme="pastel")       # soft, presentation-friendly
Figure(theme="warm")         # earthy tones, Georgia serif font
Figure(theme="ocean")        # blue palette, light blue background
Figure(theme="monochrome")   # grayscale, print-safe

# Custom theme dict
Figure(theme={
    "colors":     ["#ff6b6b", "#4ecdc4", "#45b7d1"],
    "background": "#1a1a2e",
    "text_color": "#eeeeee",
    "axis_color": "#555555",
    "grid_color": "#333333",
    "font":       "Roboto, sans-serif",
})

# Mid-chain theme swap
fig.set_theme("dark")

Accessibility note: The colorblind theme uses the Okabe-Ito palette — the scientific standard for color-vision-deficiency-safe visualization. It is safe for deuteranopia, protanopia, and tritanopia.


Export Options

fig.save("chart.svg")          # SVG vector — scales to any size
fig.save("chart.html")         # interactive HTML with tooltips, zoom, export buttons
fig.save("chart.png")          # raster PNG  (requires: pip install "glyphx[export]")
fig.save("chart.jpg")          # raster JPG  (requires: pip install "glyphx[export]")
fig.save("chart.pptx")         # PowerPoint slide (requires: pip install "glyphx[pptx]")

# Self-contained HTML — all JS inlined, works fully offline
html_str = fig.share()                       # returns string
html_str = fig.share("report.html")          # also writes to disk
html_str = fig.share(title="Q3 Report")      # custom <title> tag

fig.share() inlines all JavaScript so the output works in: email clients · Confluence · Notion · GitHub Pages · air-gapped environments


CLI Tool

Plot any CSV, JSON, or Excel file from the terminal — no Python script needed:

# Basic
glyphx plot sales.csv --x month --y revenue --kind bar -o chart.html

# Full options
glyphx plot data.csv \
    --x date --y revenue \
    --kind line \
    --groupby region \
    --agg sum \
    --theme dark \
    --title "Monthly Revenue" \
    --xlabel "Date" --ylabel "Revenue ($M)" \
    --width 900 --height 500 \
    --no-legend \
    -o report.html \
    --open          # auto-open in browser after rendering

# Column and chart suggestions for any dataset
glyphx suggest data.csv

# Print version
glyphx version

Supported inputs: .csv .tsv .json .jsonl .xlsx .xls
Supported outputs: .svg .html .png .jpg .pptx


Accessibility

Every GlyphX chart meets WCAG 2.1 AA standards automatically:

  • role="img" and aria-labelledby on every <svg> root
  • <title> and <desc> landmark elements with auto-generated descriptions
  • tabindex="0" and role="graphics-symbol" on every interactive data point
  • Tab / Arrow keys navigate between data points
  • Enter / Space triggers tooltips from keyboard
  • Escape dismisses and blurs
  • focusable="false" prevents focus stealing
# Auto-generated plain-English description for screen readers
print(fig.to_alt_text())
# → 'Line chart titled "Monthly Revenue". X axis: Month. Y axis: USD.
#    Series "Revenue": 12 data points. Ranges from 98 (Mar) to 203 (Dec).'

Type Annotations

GlyphX ships with a py.typed marker (PEP 561). All public APIs have complete type hints:

from glyphx import Figure
from glyphx.series import LineSeries

fig: Figure     = Figure(width=640, height=480, theme="dark")
s:   LineSeries = LineSeries([1, 2, 3], [4, 5, 6], label="Revenue")
fig.add(s).set_title("Typed Chart").tight_layout().show()

Works with mypy, pyright, and all major IDEs out of the box.


Comparison with Matplotlib

# Matplotlib — 12 lines, no interactivity, no shareable output
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(months, revenue, color="blue",  label="Revenue")
ax.plot(months, costs,   color="red",   label="Costs", linestyle="--")
ax.set_title("Revenue vs Costs")
ax.set_xlabel("Month")
ax.set_ylabel("USD")
ax.legend(loc="upper left")
plt.tight_layout()
plt.show()

# GlyphX — 7 lines, interactive, shareable
(Figure()
 .set_title("Revenue vs Costs")
 .set_xlabel("Month").set_ylabel("USD")
 .add(LineSeries(months, revenue, color="#2563eb", label="Revenue"))
 .add(LineSeries(months, costs, color="#dc2626", label="Costs", linestyle="dashed"))
 .set_legend("top-left").tight_layout()
 .share("report.html"))

Comparison with Seaborn

# Seaborn — significance brackets need a separate package
import seaborn as sns
from statannotations.Annotator import Annotator
ax = sns.barplot(data=df, x="group", y="score")
annotator = Annotator(ax, [("Control","Drug A")], data=df, x="group", y="score")
annotator.configure(test="t-test_ind", text_format="star")
annotator.apply_and_annotate()

# GlyphX — built-in, no extra package
(Figure()
 .add(BarSeries(["Control","Drug A","Drug B"], means, yerr=errors))
 .add_stat_annotation("Control", "Drug A", p_value=0.001)
 .add_stat_annotation("Control", "Drug B", p_value=0.031, y_offset=30)
 .show())

Comparison with Plotly

# Plotly — HTML has CDN dependency, breaks offline
import plotly.express as px
fig = px.line(df, x="month", y="revenue")
fig.write_html("chart.html")   # requires CDN at view time

# GlyphX — truly self-contained, works on a USB stick
fig.share("chart.html")        # all JS inlined, zero dependencies

Full API Reference

Figure

Method Returns Description
Figure(width, height, theme, rows, cols, legend, xscale, yscale) Figure Create figure
.add(series, use_y2=False) Figure Add a series
.line(x, y, ...) Figure Shorthand LineSeries
.bar(x, y, ...) Figure Shorthand BarSeries
.scatter(x, y, ...) Figure Shorthand ScatterSeries
.hist(data, ...) Figure Shorthand HistogramSeries
.box(data, ...) Figure Shorthand BoxPlotSeries
.heatmap(matrix, ...) Figure Shorthand HeatmapSeries
.pie(values, ...) Figure Shorthand PieSeries
.donut(values, ...) Figure Shorthand DonutSeries
.area(x, y1, y2, ...) Figure Shorthand FillBetweenSeries
.kde(data, ...) Figure Shorthand KDESeries
.ecdf(data, ...) Figure Shorthand ECDFSeries
.raincloud(data, ...) Figure Shorthand RaincloudSeries
.candlestick(dates, o, h, l, c) Figure Shorthand CandlestickSeries
.waterfall(labels, values, ...) Figure Shorthand WaterfallSeries
.treemap(labels, values, ...) Figure Shorthand TreemapSeries
.stream(max_points, ...) StreamingSeries Add streaming series; returns stream
.vline(x, ...) Figure Vertical reference line
.hline(y, ...) Figure Horizontal reference line
.set_title(text) Figure Chart title
.set_theme(name_or_dict) Figure Apply theme
.set_size(width, height) Figure Resize canvas
.set_xlabel(text) Figure X-axis label
.set_ylabel(text) Figure Y-axis label
.set_legend(position) Figure Legend position or False
.add_axes(row, col) Axes Get / create subplot cell
.annotate(text, x, y, ...) Figure Text annotation with optional arrow
.add_stat_annotation(x1, x2, p_value, ...) Figure Significance bracket
.tight_layout() Figure Auto-adjust padding and rotate labels
.enable_crosshair() Figure Synchronized crosshair
.to_alt_text() str Screen-reader description
.show() Figure Display in Jupyter or browser
.save(filename) Figure Write SVG / HTML / PNG / JPG / PPTX
.share(filename, title) str Generate self-contained HTML
.render_svg() str Raw SVG string

DataFrame Accessor (df.glyphx.*)

Method Description
.line(x, y, yerr, ...) Line chart
.bar(x, y, groupby, agg, yerr, ...) Bar chart with optional groupby
.scatter(x, y, ...) Scatter plot
.hist(col, bins, ...) Histogram of a column
.box(col, groupby, ...) Box plot, optional multi-group
.pie(labels, values, ...) Pie chart
.donut(labels, values, ...) Donut chart
.heatmap(...) Heatmap from numeric columns
.plot(kind, x, y, ...) Unified dispatcher

All accessor methods return Figure for chaining.

CLI

Command Description
glyphx plot <file> [options] Render a chart from a data file
glyphx suggest <file> Recommend chart types for a dataset
glyphx version Print version and exit

Running the Examples

git clone https://github.com/kjkoeller/glyphx
cd glyphx
pip install -e ".[all]"
python examples.py             # generates HTML files in ./glyphx_output/
OPEN=1 python examples.py      # also auto-opens each chart in browser

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

# Setup dev environment
git clone https://github.com/kjkoeller/glyphx
cd glyphx
pip install -e ".[all]"
pip install pytest pytest-cov

# Run the test suite
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=glyphx --cov-report=term-missing

Please ensure all new chart types include:

  • A series class with a to_svg(ax) method
  • Tests in tests/
  • A to_alt_text() compatible description
  • An entry in __init__.py and __all__

Roadmap

The items below are planned for upcoming releases. Contributions and feedback on priority order are welcome — open a GitHub issue or discussion.

✅ v2.1 — Competitive Foundation (shipped)

  • BubbleSeries — scatter with size encoding; missing from all three competitors
  • SunburstSeries — multi-ring hierarchical chart; previously Plotly-exclusive
  • ParallelCoordinatesSeries — high-dimensional data; Seaborn has nothing equivalent
  • DivergingBarSeries — horizontal diverging bars; no native equivalent in any competitor
  • LTTB downsampling — Largest-Triangle-Three-Buckets auto-downsampling for LineSeries; GlyphX now handles 100k+ point datasets without SVG degradation, matching Matplotlib's large-data performance
  • Hue / palette APIdf.glyphx.bar(x="month", y="revenue", hue="region") auto-splits into color-coded series with theme-aligned colors; closes Seaborn's biggest advantage
  • Fluent method chaining — every Figure method returns self
  • DataFrame accessor (df.glyphx.*) with hue= support
  • Natural language charts (from_prompt) via Claude API
  • Statistical significance brackets (add_stat_annotation)
  • Raincloud plot, ECDF, KDE, FillBetween, Candlestick, Waterfall, Treemap, Streaming
  • PPTX export, CLI tool, ARIA accessibility, full type annotations
  • LTTB downsampling — Largest-Triangle-Three-Buckets auto-downsampling for LineSeries on datasets above 5 000 points; SVG stays fast where Matplotlib would rasterize

v2.2 — Remaining Chart Gaps

  • Stacked bar chartStackedBarSeries with optional 100% percentage mode
  • Stacked area chart — additive multi-series FillBetweenSeries
  • Bump chart — rank-over-time (Seaborn cannot do this natively)
  • Forest plot — meta-analysis standard; no native equivalent in any library
  • Alluvial / Sankey diagram — flow between categorical states over time
  • ECDF with bootstrap confidence bands — shading around the step function
  • Clustermap with dendrogram — Seaborn's most distinctive chart in bioinformatics; hierarchically-clustered heatmap with tree diagrams on both axes
  • Regplot / lmplot completeness — polynomial, logistic, LOWESS, and robust regression with CI shading; beat Seaborn's regression plotting

v2.3 — Layout & Polish

  • Shared axis subplotsFigure(rows=2, shared_x=True) so all subplots share a single X axis with synchronized zoom and pan
  • Inset axisfig.inset_axes(x, y, width, height) for zoomed detail panels inside a larger plot
  • Multi-line axis labels — wrap long X-tick labels over two lines instead of forcing rotation
  • Custom tick formattersfig.axes.set_tick_format(lambda v: f"${v:,.0f}") for per-axis label control; beat Matplotlib's fine-grained axis API
  • Minor ticks — configurable minor grid subdivisions between major ticks

v2.4 — Interactivity & Export

  • Click-to-filter — click a bar or slice to cross-filter all other charts on the same HTML page, with zero server dependency
  • Animated transitions — SVG <animate> elements between data updates for streaming and dashboard refresh
  • PowerPoint multi-slideSubplotGrid.save("deck.pptx") exports each subplot to a separate slide
  • Chart diffglyphx.diff(fig_v1, fig_v2) produces an animated SVG showing what changed between two renders
  • VS Code extension — live SVG preview panel that updates on file save; no browser tab switching

v3.0 — Platform

  • Geographic / choropleth maps — GeoJSON + SVG path rendering for country/region maps without external tile dependencies
  • React / Next.js component<GlyphXChart> web component with Python-serialized config
  • WebAssembly renderer — full GlyphX in the browser via Pyodide; no Python server required
  • Collaborative dashboards — multi-user real-time dashboards over WebSocket push, no Dash or Streamlit needed
  • Figma plugin — export any GlyphX SVG to Figma as an editable vector layer

License

MIT License — © 2025 Kyle Koeller and GlyphX contributors.
See LICENSE for the full text.

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

glyphx-2.1.0.tar.gz (576.1 kB view details)

Uploaded Source

Built Distribution

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

glyphx-2.1.0-py3-none-any.whl (163.8 kB view details)

Uploaded Python 3

File details

Details for the file glyphx-2.1.0.tar.gz.

File metadata

  • Download URL: glyphx-2.1.0.tar.gz
  • Upload date:
  • Size: 576.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for glyphx-2.1.0.tar.gz
Algorithm Hash digest
SHA256 fad8619036048a3ba33eeaf0a614e4ac4436fd814d3251ba7d389a4b91300e04
MD5 558af46f4031867894bc71dd9693645b
BLAKE2b-256 520a4c94e00e7c60cb0bfb70b3d6a50178cf694eb870d443f9d1db4c2a915ef2

See more details on using hashes here.

File details

Details for the file glyphx-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: glyphx-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 163.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for glyphx-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e6935a949f70573c2e70b08205f67e47f345e2c6403252fa7a791a1ec8d3ac6d
MD5 3db708bced8093ecd677270ff8d7b915
BLAKE2b-256 c7c98b53506d9fe5ad1fed51f2bb715bb65e74b58492d450f01d7bba144867c9

See more details on using hashes here.

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