API Reference¶
glyphx.plot¶
- glyphx.plot(x=None, y=None, kind='line', data=None, legend='top-right', **kwargs)[source]¶
Unified high-level plotting function.
This is the quickest way to create a single chart. Specify
kindplusx/y(ordatafor distribution charts) and GlyphX handles scaling, theming, rendering, and display automatically.- Parameters:
x (list or None) – X-axis values. Not required for
pie,donut,hist,box, orheatmap.y (list or None) – Y-axis values or raw data for distribution charts.
kind (str) – Chart type. One of
"line","bar","scatter","pie","donut","hist","box","heatmap".data (list or None) – Explicit data array for
hist/box/pie/donut(takes priority overy).legend (str) – Legend position (
"top-right","top-left", etc.) orFalseto suppress.**kwargs – Extra keyword arguments forwarded to the Series constructor (e.g.
color,label,bins,linestyle) or to Figure (e.g.width,height,theme,xscale).
- Returns:
The Figure object (auto-displayed unless
auto_display=False).- Return type:
Examples
>>> plot([1, 2, 3], [4, 5, 6], kind="line", title="My Line") >>> plot(y=[4, 5, 6], kind="bar") >>> plot(data=[1, 3, 2, 2, 1, 4], kind="hist")
glyphx.plot3d¶
- glyphx.plot3d(x=None, y=None, z=None, kind='scatter', data=None, title='', theme='default', auto_display=True, **kwargs)[source]¶
Unified 3D plotting function - the fast path to any 3D chart type.
- Parameters:
x – Data arrays. For
"surface"x and y are 1-D grid arrays and z is a 2-D matrix.y – Data arrays. For
"surface"x and y are 1-D grid arrays and z is a 2-D matrix.z – Data arrays. For
"surface"x and y are 1-D grid arrays and z is a 2-D matrix.kind –
"scatter","surface","line","bar3d".data – Alias for z (useful for surface:
plot3d(data=Z_matrix))title – Chart title.
theme – Theme name.
auto_display – Call
.show()automatically.**kwargs – Passed to the series constructor.
- Returns:
Examples:
import numpy as np from glyphx import plot3d # 3D scatter xs = np.random.randn(300) plot3d(xs, np.random.randn(300), np.random.randn(300), kind="scatter") # Surface x = np.linspace(-3, 3, 40) X, Y = np.meshgrid(x, x) Z = np.sin(np.sqrt(X**2 + Y**2)) plot3d(x, x, Z, kind="surface", cmap="plasma", title="sin(r)")
Figure¶
- class glyphx.Figure(width: int = 640, height: int = 480, padding: int = 50, title: str | None = None, theme: str | dict[str, Any] | None = None, rows: int = 1, cols: int = 1, auto_display: bool = True, legend: str | bool | None = 'outside-right', xscale: str = 'linear', yscale: str = 'linear', shared_x: bool = False)[source]¶
Bases:
objectCentral class for creating and rendering GlyphX visualizations.
Every mutating method returns
selfso calls can be chained:fig = ( Figure(width=900) .set_theme("dark") .set_title("Monthly Revenue") .add(LineSeries(months, revenue, label="Revenue")) .annotate("Peak", x="Oct", y=5400) .share("report.html") )
- Parameters:
width – Canvas width in pixels.
height – Canvas height in pixels.
padding – Inner margin between canvas edge and plot area.
title – Optional title rendered above all plots.
theme – Theme name (str) or custom theme dict.
rows – Number of subplot rows.
cols – Number of subplot columns.
auto_display – Auto-render when
plot()or__repr__is called.legend – Legend position string, or
Falseto suppress.xscale –
"linear"or"log".yscale –
"linear"or"log".
- set_theme(theme: str | dict[str, Any]) Figure[source]¶
Apply a named theme or a custom dict and return
self.
- aggregate_line(data=None, x=None, y=None, *, hue=None, estimator='mean', ci=95, n_boot=1000, n_std=1.0, band_alpha: float = 0.2, label: str | None = None, color: str | None = None, seed: int = 42) Figure[source]¶
Plot the estimate of repeated measurements per x, with a CI band.
The equivalent of
seaborn.lineplot(): hand it raw repeated-measures data – several y values per x, from several subjects, trials or runs – and it draws the mean per x with a bootstrapped confidence band, without a manualgroupbyfirst.- Parameters:
data – A DataFrame, or
Noneto passx/yas sequences.x – Column name, or the x of each observation. Repeats are the point: every observation sharing an x forms one group.
y – Column name, or the observed value of each.
hue – Column to split into one line and band per group.
estimator –
"mean","median","sum","min","max","count", or a callable reducing an array to a scalar.ci – Confidence level 0-100 for a bootstrap interval,
"sd","se", orNonefor the line alone.n_boot – Bootstrap resamples when
ciis a number.n_std – Multiplier for the
"sd"and"se"intervals.band_alpha – Opacity of the band.
label – Series label. Defaults to the y column name.
color – Line colour. Defaults to the theme palette.
seed – Fixed, so redrawing the same data gives an identical band.
- Returns:
selffor chaining.
Example:
fig.aggregate_line(df, x="timepoint", y="score", hue="treatment")
- add_controls(*, checkboxes: str | None = None, radio: str | None = None, search: str | None = None, title: str | None = None, reset: bool = True, labels: dict[str, str] | None = None, placeholder: str | None = None) Figure[source]¶
Add filter controls beside the chart: checkboxes, radios, a search box.
Each control narrows what the chart shows, in the browser, with no server and no callback. Pass the name of a field and GlyphX reads the distinct values out of the data and builds one control per value – you do not enumerate them yourself.
A field is looked up wherever it lives: in a point’s
meta, in its owndata-attributes (percenton a pie,closeon a candlestick), or as the series label via"series". Callers should not have to know which, since it differs per chart type.Filters combine with AND, which is how a stack of controls reads: tick two regions and type a name, and you get that name within those regions. A running “Showing 12 of 40” sits underneath, announced to screen readers.
- Parameters:
checkboxes – Field to build a checkbox per value from. All start ticked – a panel that hides the data on load looks broken.
radio – Field to build a radio group from. Gets an “All” option, or there is no way back to unfiltered.
search – Field a text box filters on, case-insensitive substring.
title – Heading for the panel.
reset – Include a “Show all” button.
Falseto omit.labels – Friendlier captions per control, keyed
"checkboxes","radio","search". Defaults to the field name.placeholder – Placeholder for the search box.
- Returns:
selffor chaining.
Only meaningful for
.share()and.save()output, where the JavaScript is inlined.Example:
fig.add(ScatterSeries(x, y, meta=records)) fig.add_controls(checkboxes="region", search="customer", title="Filter")
- add_detail_panel(fields: list[str] | None = None, *, title: str | None = None, empty: str | None = None) Figure[source]¶
Show a panel that fills in with a point’s details when it is clicked.
The common case for selection events without writing any JavaScript. Pass
meta=[...]to the series and the panel lists those values for whichever point is selected; click the same point again, or press Escape, and it goes back to its empty message.Under the hood this is an ordinary listener on the public
glyphx:selectevent, so it composes rather than competes: your own listeners still fire for the same click, and cross-filtering still applies.- Parameters:
fields – Metadata keys to show, in this order.
"x","y"and"label"are also accepted and fall back to the point’s own values. A key a given point lacks is skipped. Defaults to every key that point’smetacarries, or to x/y/series for a series plotted without metadata.title – Heading for the panel.
empty – Text shown before anything is selected.
- Returns:
selffor chaining.
Only meaningful for
.share()and.save()output, where the JavaScript is inlined.Example:
fig.add(ScatterSeries(x, y, meta=records)) fig.add_detail_panel(["customer", "region"], title="Selected") fig.share("chart.html")
- enable_crossfilter(enabled: bool = True) Figure[source]¶
Let clicks in this chart filter every other opted-in chart on the page.
Clicking a bar, point or slice dims everything in every participating chart that does not share its x value; clicking the same element again, or pressing Escape, clears the filter. The x value is the join key, since that is what
data-xalready carries on every drawn element.Charts opt in individually, so a page can mix filtered charts with independent ones. The filtering runs entirely in the exported HTML – there is no server, no callback round-trip, and nothing leaves the page, which is what Dash or Streamlit are normally needed for.
Only meaningful for
.share()and.save()output, where the JavaScript is inlined. A barerender_svg()string carries the marker but has no script to act on it.- Parameters:
enabled –
Falseto opt this chart back out.- Returns:
selffor chaining.
Example:
revenue = Figure().bar(months, revenue).enable_crossfilter() costs = Figure().bar(months, costs).enable_crossfilter() SubplotGrid(1, 2).add(revenue, 0, 0).add(costs, 0, 1).save("d.html") # clicking "Feb" in either chart dims every other month in both
- set_y2label(label: str) Figure[source]¶
Label the secondary (right-hand) Y axis, and return
self.Only drawn when the figure has series added with
use_y2=True.Example:
fig.add(LineSeries(x, price), ) fig.add(BarSeries(x, volume), use_y2=True) fig.set_ylabel("Price ($)").set_y2label("Volume")
- set_legend(position: str | bool | None) Figure[source]¶
Set legend position (or
Falseto hide) and returnself.
- add_axes(row: int = 0, col: int = 0) Axes[source]¶
Create or retrieve the Axes at a grid position.
- Parameters:
- Returns:
The axes at that position, created on first access.
- Return type:
- Raises:
IndexError – If the position is outside the figure’s grid.
- add(series: Any, use_y2: bool = False) Figure[source]¶
Add a series to the figure.
Returns
selfso calls can be chained:fig.add(LineSeries(...)).add(BarSeries(...)).show()
- line(x, y, color=None, label=None, linestyle='solid', width=2, yerr=None, xerr=None, use_y2=False, **kwargs) Figure[source]¶
Add a
LineSeries. Returnsself.
- bar(x, y, color=None, label=None, bar_width=0.8, yerr=None, use_y2=False, **kwargs) Figure[source]¶
Add a
BarSeries. Returnsself.
- scatter(x, y, color=None, label=None, size=5, c=None, cmap='viridis', use_y2=False, **kwargs) Figure[source]¶
Add a
ScatterSeries. Returnsself.
- hist(data, bins=20, color=None, label=None, **kwargs) Figure[source]¶
Add a
HistogramSeries. Returnsself.
- box(data, categories=None, color=None, box_width=20, **kwargs) Figure[source]¶
Add a
BoxPlotSeries. Returnsself.
- heatmap(matrix, row_labels=None, col_labels=None, show_values=False, cmap=None, **kwargs) Figure[source]¶
Add a
HeatmapSeries. Returnsself.
- donut(values, labels=None, colors=None, **kwargs) Figure[source]¶
Add a
DonutSeries. Returnsself.
- area(x, y1, y2=0, color=None, alpha=0.25, line_width=1, label=None, **kwargs) Figure[source]¶
Add a
FillBetweenSeries. Returnsself.
- kde(data, filled=False, alpha=0.2, color=None, width=2, label=None, **kwargs) Figure[source]¶
Add a
KDESeries. Returnsself.
- ecdf(data, color=None, label=None, complementary=False, **kwargs) Figure[source]¶
Add a
ECDFSeries. Returnsself.
- raincloud(data, categories=None, seed=42, violin_width=40, **kwargs) Figure[source]¶
Add a
RaincloudSeries. Returnsself.
- candlestick(dates, open, high, low, close, label=None, **kwargs) Figure[source]¶
Add a
CandlestickSeries. Returnsself.
- waterfall(labels, values, show_values=True, **kwargs) Figure[source]¶
Add a
WaterfallSeries. Returnsself.
- treemap(labels, values, cmap='viridis', show_values=True, **kwargs) Figure[source]¶
Add a
TreemapSeries. Returnsself.
- bubble(x, y, size, color=None, c=None, cmap='viridis', alpha=0.65, min_radius=4, max_radius=40, labels=None, label=None, use_y2=False, **kwargs) Figure[source]¶
Add a
BubbleSeries. Returnsself.
- sunburst(labels, parents, values, cmap='viridis', **kwargs) Figure[source]¶
Add a
SunburstSeries. Returnsself.
- parallel_coords(data, axes, hue=None, cmap='viridis', alpha=0.45, **kwargs) Figure[source]¶
Add a
ParallelCoordinatesSeries. Returnsself.
- diverging_bar(categories, values, pos_color='#2563eb', neg_color='#dc2626', show_values=True, **kwargs) Figure[source]¶
Add a
DivergingBarSeries. Returnsself.
- stream(max_points=100, color=None, label=None, **kwargs) Figure[source]¶
Add a
StreamingSeriesand return it.Unlike other shorthand methods, this returns the series (not self) so callers can push data to it:
stream = fig.stream(max_points=100, label="Sensor") stream.push(42.0)
- axhspan(ymin: float, ymax: float, color: str = '#facc15', alpha: float = 0.2, label: str | None = None) Figure[source]¶
Add a horizontal shaded band across the full chart width.
Equivalent to Matplotlib’s
ax.axhspan(). Y values are in data space; the band is clipped to the plot area.- Parameters:
ymin – Lower Y bound (data units).
ymax – Upper Y bound (data units).
color – Fill color.
alpha – Fill opacity 0-1.
label – Optional legend label.
- Returns:
selffor chaining.
Example:
fig.axhspan(90, 110, color="#22c55e", alpha=0.15, label="Target range")
- axvspan(xmin, xmax, color: str = '#a855f7', alpha: float = 0.2, label: str | None = None) Figure[source]¶
Add a vertical shaded band across the full chart height.
Equivalent to Matplotlib’s
ax.axvspan(). X values may be numeric data values or category label strings.- Parameters:
xmin – Left X bound (data units or category label).
xmax – Right X bound.
color – Fill color.
alpha – Fill opacity 0-1.
label – Optional legend label.
- Returns:
selffor chaining.
Example:
fig.axvspan("Jul", "Sep", color="#f59e0b", alpha=0.15, label="Q3")
- set_xticks(ticks: list, labels: list | None = None) Figure[source]¶
Set explicit X-axis tick positions (and optionally their labels).
Equivalent to Matplotlib’s
ax.set_xticks()+ax.set_xticklabels().- Returns:
selffor chaining.
Example:
fig.set_xticks([0, 25, 50, 75, 100]) fig.set_xticks([1, 6, 12], labels=["Jan", "Jun", "Dec"])
- set_yticks(ticks: list, labels: list | None = None) Figure[source]¶
Set explicit Y-axis tick positions (and optionally their labels).
- Returns:
selffor chaining.
Example:
fig.set_yticks([0, 500_000, 1_000_000], labels=["$0", "$500k", "$1M"])
- set_tick_format(formatter) Figure[source]¶
Apply a callable formatter to all numeric tick labels on both axes.
Equivalent to Matplotlib’s
FuncFormatter.- Parameters:
formatter – Callable
(value: float) -> str.- Returns:
selffor chaining.
Example:
fig.set_tick_format(lambda v: f"${v:,.0f}") fig.set_tick_format(lambda v: f"{v:.1%}")
- inset_axes(x: float, y: float, width: float, height: float, *, theme=None, padding: float | None = None, background: str | None = None, show_grid: bool = True)[source]¶
Add a small panel drawn on top of the main plot area.
Useful for a zoomed detail view of a dense region, or an overview thumbnail alongside a zoomed main chart. Returns a fresh
Axeswith its own independent scales – add series to it withadd_series(), exactly as withadd_axes()for subplot grids.Position and size are fractions of the figure canvas, not of the plot area, so
inset_axes(0.6, 0.1, 0.35, 0.3)always lands in the top-right regardless of how padding changes.Insets render after the main series and in the order added, so a later inset overlaps an earlier one. They are drawn over an opaque background by default so the parent’s grid lines do not show through.
- Parameters:
x – Left edge, 0-1 fraction of figure width.
y – Top edge, 0-1 fraction of figure height.
width – Panel width, 0-1 fraction of figure width.
height – Panel height, 0-1 fraction of figure height.
theme – Theme name or dict. Defaults to the parent’s theme.
padding – Inner padding in px. Defaults to a value scaled to the panel size, since the figure default of 50 would consume most of a small inset.
background – Panel fill. Defaults to the theme background. Pass
"none"for a transparent inset.show_grid – Draw grid lines inside the panel.
- Returns:
the inset’s axes.
- Return type:
- Raises:
ValueError – If the panel is not within the canvas, or has non-positive size.
Example:
fig = Figure().line(x, y) inset = fig.inset_axes(0.6, 0.15, 0.35, 0.3) inset.add_series(LineSeries(x[:20], y[:20]))
- set_tick_wrap(enabled: bool = True) Figure[source]¶
Wrap long X-axis tick labels onto a second line instead of rotating.
- Parameters:
enabled –
Trueto wrap,Falseto restore auto-rotation.- Returns:
selffor chaining.
Example:
fig.bar(["Product Engineering", "Sales & Marketing"], [10, 20]) fig.set_tick_wrap()
- set_minor_ticks(n: int = 4) Figure[source]¶
Draw minor tick subdivisions between each pair of major ticks.
- Parameters:
n – Number of minor ticks between major ticks.
- Returns:
selffor chaining.
Example:
fig.set_minor_ticks(4)
- set_spine_visible(left: bool = True, right: bool = True, top: bool = False, bottom: bool = True) Figure[source]¶
Control axis spine (border line) visibility.
Equivalent to Matplotlib’s
ax.spines[...].set_visible().- Parameters:
left – Left (Y) spine.
right – Right (Y2) spine.
top – Top spine.
bottom – Bottom (X) spine.
- Returns:
selffor chaining.
Example:
fig.set_spine_visible(top=False, right=False) # clean minimal look
- text(x: float, y: float, s: str, color: str = '#333', font_size: int = 12, anchor: str = 'middle', transform: str = 'canvas') Figure[source]¶
Add free-form text anywhere on the canvas.
Equivalent to Matplotlib’s
fig.text()/ax.text().- Parameters:
x – X position. When
transform='canvas'this is a fraction of canvas width (0-1). Whentransform='data'it is a data-space value.y – Y position. Canvas fraction (0 = top, 1 = bottom) or data-space value depending on
transform.s – Text string. Use
$...$for math (rendered via MathJax when the chart is opened in a browser).color – Font color.
font_size – Font size in points.
anchor – SVG text-anchor:
"start","middle","end".transform –
"canvas"(0-1 fractions) or"data"(data coords).
- Returns:
selffor chaining.
Example:
fig.text(0.5, 0.02, "Source: World Bank", font_size=9, color="#888") fig.text(0.5, 0.5, "$R^2 = 0.95$", font_size=14)
- supxlabel(label: str, font_size: int = 13, color: str | None = None) Figure[source]¶
Set a shared X-axis label below all subplots.
Equivalent to Matplotlib’s
fig.supxlabel(). Useful when all subplots in a grid share the same X-axis meaning.- Parameters:
label – Label text.
font_size – Font size.
color – Text color (defaults to theme text color).
- Returns:
selffor chaining.
- supylabel(label: str, font_size: int = 13, color: str | None = None) Figure[source]¶
Set a shared Y-axis label beside all subplots.
Equivalent to Matplotlib’s
fig.supylabel().- Parameters:
label – Label text.
font_size – Font size.
color – Text color (defaults to theme text color).
- Returns:
selffor chaining.
- to_vega_lite(path: str | None = None, **kwargs) dict[source]¶
Convert this figure to a Vega-Lite v5 specification.
The spec can be saved as a
.vl.jsonfile, embedded in Observable notebooks, or rendered withaltair. No Python plotting library currently produces Vega-Lite output.- Parameters:
path – If given, write the spec to this JSON file.
- Returns:
Vega-Lite v5 specification dict.
Example:
spec = fig.to_vega_lite() fig.to_vega_lite("chart.vl.json") # saves to file
- regplot(data=None, x=None, y=None, x_vals=None, y_vals=None, **kwargs) Figure[source]¶
Add a regression plot series to this figure. Returns
self.
- choropleth(geojson, data, key='name', cmap='viridis', **kwargs) Figure[source]¶
Add a
ChoroplethSeries. Returnsself.
- gantt(tasks: list, group_colors: dict | None = None, cmap: str = 'viridis', bar_height: int = 20, show_today: bool = True, **kwargs) Figure[source]¶
Add a
GanttSeries. Returnsself.
- stacked_bar(x: list, series: dict, normalize: bool = False, colors: list | None = None, bar_width: float = 0.75, **kwargs) Figure[source]¶
Add a
StackedBarSeries. Returnsself.
- bump(x: list, rankings: dict, colors: list | None = None, show_labels: bool = True, **kwargs) Figure[source]¶
Add a
BumpChartSeries. Returnsself.
- sparkline(data: list, color: str = '#2563eb', kind: str = 'line', fill: bool = True, label: str | None = None, **kwargs) Figure[source]¶
Add a
SparklineSeries. Returnsself.
- vline(x, color='#888', width=1, linestyle='dashed', label=None) Figure[source]¶
Draw a vertical reference line at data coordinate
x. Returnsself.
- hline(y, color='#888', width=1, linestyle='dashed', label=None) Figure[source]¶
Draw a horizontal reference line at data coordinate
y. Returnsself.
- copy() Figure[source]¶
Return a deep copy of this figure.
Useful for creating small variations without re-building from scratch:
base = Figure().add(LineSeries(x, y)) dark = base.copy().set_theme("dark") light = base.copy().set_theme("default")
Series, annotations, and settings are all duplicated.
- annotate(text: str, x: float, y: float, color: str = '#333', font_size: int = 12, anchor: str = 'start', arrow: bool = False, ax_x: float | None = None, ax_y: float | None = None) Figure[source]¶
Add a text annotation in data-space coordinates.
Returns
selffor chaining.- Parameters:
text – Label text.
x – Data-space X coordinate of the annotation point.
y – Data-space Y coordinate.
color – Text and arrow colour.
font_size – Label font size in points.
anchor – SVG text-anchor (
"start","middle","end").arrow – Draw a small leader line from text to point.
ax_x – Arrow tail X pixel offset (default −8).
ax_y – Arrow tail Y pixel offset (default −8).
- to_alt_text() str[source]¶
Generate a plain-English description of this figure for screen readers.
- Returns:
A human-readable string suitable for
aria-labelor<desc>.
- render_svg(viewbox: bool = False) str[source]¶
Render the complete figure and return an SVG string.
The SVG includes: -
role="img"andaria-labelledbyon the root element -<title>and<desc>ARIA landmark children -tabindex="0"on every interactive data point- Returns:
Complete SVG document markup.
- to_html_fragment(interactive: bool = True) str[source]¶
Render an HTML fragment suitable for embedding in a page.
Unlike
save()with an.htmlpath, this returns a fragment with no<html>wrapper, so it can be dropped into a notebook output cell, a Jinja template, or a dashboard.
- render_responsive(dark_theme: str | None = None) str[source]¶
Render an SVG that responds to the OS dark-mode preference.
The output uses CSS custom properties (
--glyphx-bg, etc.). When the user switches dark mode, the chart recolours without any Python re-render – a capability none of the three competitors have.- Parameters:
dark_theme – GlyphX theme name for dark mode (default
'dark').- Returns:
Complete
<svg>string with embedded CSS variable block.
Example:
svg = fig.render_responsive(dark_theme='dark') fig.save('chart.svg') # handles encoding and the XML declaration # Open in a browser -- switches colours with the OS setting
- save(filename: str = 'glyphx_output.svg', dpi: int = 96, backend: str | None = None) Figure[source]¶
Save the rendered figure to disk.
.svgand.htmlneed no extra packages..png,.jpg,.webp, and.pdfuse whichever rendering backend is installed (seeglyphx.export);.pptxneeds the pptx extra:pip install "glyphx[export]" # PNG/JPG/WEBP via resvg pip install "glyphx[cairo]" # adds PDF pip install "glyphx[pptx]" # PowerPoint
- Parameters:
filename – Output path. Extension determines the format.
dpi – Output resolution for raster formats. Default 96; use 192 for retina or 300 for print. No effect on SVG, HTML, or PDF.
backend – Force a specific export backend (“resvg”, “cairosvg”, or “playwright”). Defaults to the best available.
- Returns:
selffor chaining.
Example:
fig.save("chart.png", dpi=192) # crisp on retina displays fig.save("chart.pdf") # vector, for print
- tight_layout() Figure[source]¶
Auto-adjust padding to prevent label clipping and overlap.
For single-axis figures, delegates to
tight_layout(). For subplot grids, appliesconstrained_layout()which aligns the left edges of all subplot cells so tick labels never overlap across rows.Returns
selffor chaining.
- constrained_layout() Figure[source]¶
Align subplot cells so their plot areas share a common left edge.
Equivalent to Matplotlib’s
constrained_layout=True. Computes the widest Y-tick label across all cells in each column, then sets a uniform left padding for all cells in that column so the actual data area (to the right of the Y-axis) is flush.Returns
selffor chaining.Example:
fig = Figure(rows=2, cols=2, width=900, height=600) # ... add_axes and add_series ... fig.constrained_layout() # aligns all subplot left edges
- add_stat_annotation(x1: Any, x2: Any, p_value: float = 0.05, label: str | None = None, style: str = 'stars', color: str = '#222', y_offset: float = 0.0) Figure[source]¶
Add a significance bracket between two groups.
Draws
***/**/*/nsabove the bracket based on p_value. Works with both numeric and categorical X axes.- Parameters:
x1 – First group (label or numeric X value).
x2 – Second group.
p_value – Statistical p-value.
label – Override the auto-generated significance label.
style –
"stars"or"numeric".color – Bracket and text color.
y_offset – Extra upward shift in pixels (stack multiple brackets).
- Returns:
selffor chaining.
- enable_crosshair() Figure[source]¶
Enable the synchronized crosshair on the next
share()/show()call.The crosshair draws a vertical line across all GlyphX charts on the same HTML page and highlights the nearest data point in each.
Returns
self.
Generate a fully self-contained, shareable HTML document.
The output embeds all JavaScript inline – no CDN, no server, works offline. Pass
filenameto also write it to disk.- Returns:
Complete HTML document string.
Figure3D¶
- class glyphx.Figure3D(width: int = 900, height: int = 650, title: str = '', theme: str = 'default', azimuth: float = 45.0, elevation: float = 30.0, xlabel: str = 'X', ylabel: str = 'Y', zlabel: str = 'Z')[source]¶
Bases:
object3D chart canvas.
Renders to self-contained HTML with interactive Three.js WebGL, or falls back to an orthographic SVG for static export.
- Parameters:
width – HTML canvas width (
"100%"or pixel value).height – HTML canvas height.
title – Chart title.
theme – Theme name (same as
Figure).azimuth – Initial camera azimuth in degrees (SVG and HTML).
elevation – Initial camera elevation in degrees (SVG only).
xlabel – X-axis label.
ylabel – Y-axis label.
zlabel – Z-axis label.
Example:
from glyphx import Figure3D from glyphx.surface3d import Surface3DSeries import numpy as np x = np.linspace(-3, 3, 50) y = np.linspace(-3, 3, 50) X, Y = np.meshgrid(x, y) Z = np.sin(np.sqrt(X**2 + Y**2)) fig = Figure3D(title="sin(r)", theme="dark") fig.add(Surface3DSeries(x, y, Z, cmap="plasma")) fig.show()
- scatter(x, y, z, color='#2563eb', c=None, cmap='viridis', size=5, label=None, alpha=0.85) Figure3D[source]¶
Add a
Scatter3DSeries. Returnsself.
- surface(x, y, z, cmap='viridis', alpha=0.9, wireframe=True) Figure3D[source]¶
Add a
Surface3DSeries. Returnsself.
- line3d(x, y, z, color='#dc2626', width=2, linestyle='solid', label=None) Figure3D[source]¶
Add a
Line3DSeries. Returnsself.
- bar3d(x, y, z, cmap='viridis', alpha=0.85, label=None) Figure3D[source]¶
Add a
Bar3DSeries. Returnsself.
Axes¶
- class glyphx.layout.Axes(width=600, height=400, padding=50, show_grid=True, theme=None, legend=None, xscale='linear', yscale='linear', precision=2)[source]¶
Bases:
objectManages axis scaling, tick rendering, and series layout within a plot.
Supports: - Dual Y-axes (primary and secondary) - Categorical X-axis labels - Linear and log-scale axes - Configurable tick counts and grid lines - Axis title / xlabel / ylabel labels
- add_series(series, use_y2=False)[source]¶
Register a series on the primary or secondary Y-axis.
- Parameters:
series (BaseSeries) – Any series with
.xand.yattributes.use_y2 (bool) – If True, bind to the right-hand Y-axis.
- axhspan(ymin: float, ymax: float, color: str = '#ffff00', alpha: float = 0.2, label: str | None = None) Axes[source]¶
Add a horizontal shaded band spanning the full plot width.
The band is drawn in data-space Y coordinates. Values outside the current Y domain are clipped to the plot boundary.
- Parameters:
ymin – Lower Y data value of the band.
ymax – Upper Y data value of the band.
color – Fill color.
alpha – Fill opacity 0–1.
label – Optional legend label.
- Returns:
selffor chaining.
Example:
ax.axhspan(90, 110, color="#22c55e", alpha=0.15, label="Normal range")
- axis_metadata() str[source]¶
The plot rectangle and data domains, as
data-attributes.Zooming rewrites the SVG’s
viewBox, which crops the axis labels along with everything else – they are static text positioned for the original domain. Publishing the geometry lets zoom.js map the visible region back to data coordinates and redraw the ticks for whatever is actually on screen.- Returns:
Attribute string, or
""when there is no domain yet.- Return type:
- axvspan(xmin, xmax, color: str = '#a855f7', alpha: float = 0.2, label: str | None = None) Axes[source]¶
Add a vertical shaded band spanning the full plot height.
xmin/xmaxmay be numeric data values or category label strings (resolved to their numeric position).- Parameters:
xmin – Left X data value of the band.
xmax – Right X data value of the band.
color – Fill color.
alpha – Fill opacity 0–1.
label – Optional legend label.
- Returns:
selffor chaining.
Example:
ax.axvspan("Jul", "Sep", color="#f59e0b", alpha=0.15, label="Summer")
- compute_domain(series_list)[source]¶
Compute
(x_domain, y_domain)from a list of series.Categorical string X-values are converted to numeric indices. The conversion is stored on the series as
._numeric_xso the originalseries.xis never mutated.When multiple series each carry different categories (e.g. one bar per group from a groupby aggregation), all unique categories are merged into a single global ordering so each gets a distinct x position.
- finalize()[source]¶
Compute all scale functions after series have been registered.
Must be called before any rendering method.
- render_axes()[source]¶
Render X, Y, and (if y2_series exist) Y2 axis lines plus labels.
- Returns:
SVG elements for axes.
- Return type:
- render_grid(ticks=5)[source]¶
Render tick marks, grid lines, and numeric labels.
Categorical X-axes replace numeric labels with the original category names.
- set_minor_ticks(n: int, length: float = 2.0) Axes[source]¶
Draw
nminor tick subdivisions between each pair of major ticks.- Parameters:
n – Number of minor ticks between major ticks (e.g. 4 gives 5 equal sub-intervals).
length – Minor tick length in pixels.
- Returns:
selffor chaining.
Example:
ax.set_minor_ticks(4) # quarterly subdivisions on annual axis
- set_spine_visible(left: bool = True, right: bool = True, top: bool = False, bottom: bool = True) Axes[source]¶
Control which axis spines (border lines) are visible.
By default the top spine is hidden (matches Matplotlib’s
ax.spinesbest-practice for clean scientific plots).- Parameters:
left – Show left (Y) spine.
right – Show right (Y2) spine.
top – Show top spine.
bottom – Show bottom (X) spine.
- Returns:
selffor chaining.
Example:
ax.set_spine_visible(top=False, right=False) # clean minimal look
- set_tick_format(formatter) Axes[source]¶
Apply a callable formatter to all numeric tick labels.
The formatter receives a float and must return a string. It applies to both X and Y axes (use
set_xticklabels/set_yticklabelsto override one axis independently).- Parameters:
formatter – Callable
(value: float) -> str.- Returns:
selffor chaining.
Example:
ax.set_tick_format(lambda v: f"${v:,.0f}") ax.set_tick_format(lambda v: f"{v:.1%}")
- set_tick_wrap(enabled: bool = True) Axes[source]¶
Wrap long X-axis tick labels onto a second line instead of rotating.
Rotation is GlyphX’s automatic default once labels would overlap at horizontal angle (see
_should_rotate_xlabels); this is an explicit alternative for when rotated text is harder to read than two short lines – category names and month/quarter labels are the common case. The two are mutually exclusive: enabling wrap suppresses auto-rotation for this axes.- Parameters:
enabled –
Trueto wrap,Falseto restore the default (auto-rotate when labels would otherwise overlap).- Returns:
selffor chaining.
Example:
ax.set_tick_wrap() # "Product Engineering" wraps onto two lines
- set_xticklabels(labels: list[str]) Axes[source]¶
Override X-tick display strings without changing positions.
- set_xticks(ticks: list, labels: list[str] | None = None) Axes[source]¶
Set explicit X-axis tick positions.
- Parameters:
ticks – List of data-space positions where ticks should appear.
labels – Optional list of strings to display instead of formatted values. Must be the same length as
ticks.
- Returns:
selffor chaining.
Example:
ax.set_xticks([0, 25, 50, 75, 100]) ax.set_xticks([1, 6, 12], labels=["Jan", "Jun", "Dec"])
- set_y2label(label: str) Axes[source]¶
Label the secondary (right-hand) Y axis.
Rendered rotated on the right edge, mirroring
ylabel. Only drawn when the axes actually hasy2_series, so setting it on a single-axis chart is a harmless no-op.- Parameters:
label – Text for the right-hand axis.
- Returns:
selffor chaining.
- set_yticklabels(labels: list[str]) Axes[source]¶
Override Y-tick display strings without changing positions.
- set_yticks(ticks: list, labels: list[str] | None = None) Axes[source]¶
Set explicit Y-axis tick positions.
- Parameters:
ticks – List of data-space positions.
labels – Optional display labels (same length as ticks).
- Returns:
selffor chaining.
Example:
ax.set_yticks([0, 1_000_000, 2_000_000], labels=["$0", "$1M", "$2M"])
layout.grid¶
SubplotGrid¶
- class glyphx.figure.SubplotGrid(rows: int, cols: int)[source]¶
Bases:
objectStandalone 2-D grid for laying out existing Figure objects into one page.
Example:
sg = SubplotGrid(2, 2) sg.add(fig_revenue, 0, 0) sg.add(fig_costs, 0, 1) html = sg.render() with open("dashboard.html", "w", encoding="utf-8") as fh: fh.write(html)
- Parameters:
rows – Number of rows.
cols – Number of columns.
- add(figure: Figure, row: int, col: int) SubplotGrid[source]¶
Place a Figure at a grid position. Returns
self.
- add_axes(row: int, col: int, figure: Figure) SubplotGrid[source]¶
Alias for
add()kept for backward compatibility.
- render(gap: int = 20) str[source]¶
Render all figures into a self-contained HTML page.
- Returns:
Full HTML document string.
- save(filename: str = 'glyphx_dashboard.html', dpi: int = 96, backend: str | None = None) SubplotGrid[source]¶
Save the grid to disk.
.htmlwrites the same composite pagerender()produces..pptxputs each figure on its own slide, in row-major order, titled from the figure’s owntitleif it set one – this is the multi-slide export the standaloneSubplotGridhad no way to do before, sinceFigure.save()only ever knew about one figure..svg,.png,.jpgand.pdfare not supported: those formats have no multi-page notion, and the grid’s cells sit in separate<svg>documents rather than one combined one, so there is no single image to rasterise. Save eachFigurein the grid individually for those formats.- Parameters:
filename – Output path. Extension selects the format.
dpi – Forwarded to the PNG rasteriser that PPTX export uses internally. No effect on
.html.backend – Unused; accepted for signature parity with
Figure.save().
- Returns:
selffor chaining.- Raises:
ValueError – For an unsupported extension.
Example:
sg = SubplotGrid(2, 2) sg.add(revenue_fig, 0, 0).add(costs_fig, 0, 1) sg.save("quarterly_review.pptx") # one slide per figure
Core Series¶
- class glyphx.series.BaseSeries(x, y=None, color=None, label=None, title=None)[source]¶
Bases:
objectBase class for all GlyphX series.
- class glyphx.series.LineSeries(x, y, color=None, label=None, legend=None, linestyle='solid', width=2, title=None, yerr=None, xerr=None, markers='auto', threshold=None)[source]¶
Bases:
BaseSeriesLine chart series with optional error bars.
- Parameters:
x (list) – X values.
y (list) – Y values.
color (str | None) – Line/point color.
label (str | None) – Legend label.
linestyle (str) –
"solid","dashed","dotted", or"longdash".width (int) – Stroke width in pixels.
title (str | None) – Chart subtitle.
yerr (list | None) – Symmetric Y error bar values (same length as y).
xerr (list | None) – Symmetric X error bar values (same length as x).
markers (bool | str) – Draw a hoverable circle per data point.
"auto"(default) draws them only when the series has at mostMARKER_LIMITpoints, since one DOM node per point dominates document size and stalls the browser on dense series.
- MARKER_LIMIT = 400¶
Above this many points, “auto” markers are suppressed. 400 is where Chrome started dropping frames for me on a 2019 laptop; it is a guess, not a measurement anyone should rely on.
- to_svg(ax, use_y2=False)[source]¶
Draw the line, thinning the data first if it has more points than pixels.
An M4 pass preserves the per-column extremes, then LTTB thins what remains, so a million-point series renders in the time a few thousand would without losing spikes. What happened is recorded on
last_downsample_infofor anyone who needs to check.
- class glyphx.series.BarSeries(x, y, color=None, label=None, legend=None, bar_width=0.8, title=None, yerr=None)[source]¶
Bases:
BaseSeriesBar chart series with optional error bars.
- Parameters:
x – X-axis labels/values.
y – Bar heights.
color – Fill color.
label – Legend label.
bar_width (float) – Fraction of available slot width (0–1).
title – Per-series subtitle.
yerr – Symmetric Y error values.
- to_svg(ax, use_y2=False)[source]¶
Draw the bars, taking their width from the axes’ own category spacing.
Width comes from
scale_x(start + 1) - scale_x(start)rather than dividing the plot area by this series’ category count, so bars stay aligned when several series share an axes and cover different categories.
- class glyphx.series.ScatterSeries(x, y, color=None, label=None, legend=None, size=5, marker='circle', title=None, c=None, cmap='viridis', sizes=None, style=None, style_order=None, threshold=None, meta=None)[source]¶
Bases:
BaseSeriesScatter plot with configurable marker type, size, and continuous color encoding.
- Parameters:
marker (str) –
"circle"or"square".size (int) – Marker radius / half-width in pixels.
c (list | None) – Per-point values for color encoding. When set, each point’s color is determined by mapping this value through
cmap. Overridescolor.cmap (str) – Colormap name (default:
"viridis"). Seelist_colormaps()for options.
- class glyphx.series.HistogramSeries(data, bins=10, color=None, label=None, hue=None, hue_colors=None, cmap='viridis', alpha=0.65)[source]¶
Bases:
BaseSeriesFrequency distribution histogram.
- Parameters:
data (array-like) – Raw numeric values.
bins (int) – Number of histogram bins.
color – Bar fill color.
label – Legend label.
- class glyphx.series.BoxPlotSeries(data, categories=None, color='#1f77b4', label=None, box_width=20, width=None, hue=None, hue_colors=None, cmap='viridis')[source]¶
Bases:
BaseSeriesBox-and-whisker plot.
Supports a single array (one box) or a list of arrays (multiple boxes drawn at categorical X positions).
- Parameters:
- class glyphx.series.HeatmapSeries(matrix, cmap=None, row_labels=None, col_labels=None, show_values=False, *, vmin=None, vmax=None, center=None, **kwargs)[source]¶
Bases:
BaseSeriesHeatmap for 2-D matrix data with a color-scale legend.
- class glyphx.series.PieSeries(values, labels=None, colors=None, title=None, label_position='outside', radius=None)[source]¶
Bases:
BaseSeriesPie chart series.
- Parameters:
values (list) – Numeric slice sizes.
labels (list | None) – Label for each slice.
colors (list | None) – Color per slice (cycles if fewer than slices).
title (str | None) – Chart title rendered above the pie.
label_position (str) –
"outside"(default) or"inside".radius (float) – Explicit radius in pixels; auto-computed if None.
- class glyphx.series.DonutSeries(values, labels=None, colors=None, show_labels=True, hover_animate=True, inner_radius_frac=0.5)[source]¶
Bases:
BaseSeriesDonut (annular pie) chart series.
- Parameters:
values (list) – Numeric slice sizes.
labels (list | None) – Label per slice; auto-generated if None.
colors (list | None) – Color per slice.
show_labels (bool) – Draw callout labels outside the ring.
hover_animate (bool) – Add
glyphx-pointclass for CSS hover.inner_radius_frac (float) – Hole radius as fraction of outer radius.
Statistical Series¶
- class glyphx.ecdf.ECDFSeries(data: list | ndarray, color: str | None = None, label: str | None = None, show_points: bool = False, point_radius: float = 3.0, line_width: float = 2.0, complementary: bool = False)[source]¶
Bases:
BaseSeriesEmpirical CDF rendered as a step function.
- Parameters:
data – Raw observations (1-D array-like).
color – Line color.
label – Legend label.
show_points – Draw a circle at each step.
point_radius – Radius of step-point circles.
line_width – Stroke width of the step line.
complementary – If True, plot 1 − ECDF (survival function).
- class glyphx.raincloud.RaincloudSeries(data: list, categories: list[str] | None = None, colors: list[str] | None = None, jitter_width: float = 18.0, point_radius: float = 3.0, violin_width: float = 40.0, box_width: float = 10.0, seed: int = 42, label: str | None = None)[source]¶
Bases:
objectRaincloud plot: jitter + half-violin + box for each category.
- Parameters:
data – List of 1-D arrays, one per category.
categories – Category labels (same length as data).
colors – Per-category colors; cycles if fewer than categories.
jitter_width – Max horizontal pixel displacement of raw points.
point_radius – Radius of each jittered data point.
violin_width – Max pixel width of the half-violin.
box_width – Pixel width of the IQR box.
seed – Random seed for reproducible jitter.
label – Legend label for the series.
- class glyphx.violin_plot.ViolinPlotSeries(data, positions=None, color='#1f77b4', width=50, show_median=True, show_box=True, label=None, hue=None, hue_colors=None, cmap='viridis', categories=None)[source]¶
Bases:
objectViolin plot: a KDE-smoothed distribution mirrored on both sides of a centre line.
Requires no external dependencies beyond NumPy.
- Parameters:
data (list of array-like) – One array per category.
positions (list | None) – X-axis positions for each violin.
color (str) – Fill/stroke color.
width (int) – Maximum pixel half-width of the violin body.
show_median (bool) – Draw a horizontal median marker.
show_box (bool) – Overlay a thin IQR box inside the violin.
label (str | None) – Legend label.
- class glyphx.kde.KDESeries(data, n_points: int = 200, filled: bool = False, alpha: float = 0.2, color: str = '#1f77b4', width: int = 2, label: str | None = None, bw_method: str | float = 'silverman')[source]¶
Bases:
BaseSeriesSmooth kernel density estimate curve (no scipy required).
- Parameters:
data – 1-D array of raw observations.
n_points – Number of evaluation points along the curve (default 200).
filled – If
True, shade the area under the curve.alpha – Fill opacity when
filled=True(default 0.20).color – Line (and fill) color.
width – Line stroke width in pixels.
label – Legend label.
bw_method – Bandwidth:
"silverman"(default) or a positive float multiplier applied to the Silverman estimate.
- class glyphx.fill_between.FillBetweenSeries(x, y1, y2, color: str = '#1f77b4', alpha: float = 0.25, line_width: int = 1, label: str | None = None, line_color: str | None = None)[source]¶
Bases:
BaseSeriesShaded area between two Y arrays (or between a line and a baseline).
- Parameters:
x – X values (shared by both bounds).
y1 – Lower bound Y values, or the line when
y2is a scalar.y2 – Upper bound Y values. Pass a scalar (e.g.
0) to shade betweeny1and a horizontal baseline.color – Fill and line color (default:
"#1f77b4").alpha – Fill opacity 0–1 (default:
0.25).line_width – Width of the boundary lines in pixels.
0hides them.label – Legend label.
line_color – Color for boundary lines. Defaults to
color.
- class glyphx.stat_annotation.StatAnnotation(x1: Any, x2: Any, p_value: float = 0.05, label: str | None = None, style: str = 'stars', color: str = '#222', line_width: float = 1.5, tip_len: float = 8.0, y_offset: float = 0.0)[source]¶
Bases:
objectSignificance bracket drawn between two groups on a chart.
- x1¶
First group label or numeric X value.
- x2¶
Second group label or numeric X value.
- p_value¶
The p-value for the test between the two groups.
- label¶
Override text (defaults to significance stars).
- style¶
"stars"or"numeric".
- color¶
Line and text color.
- line_width¶
Bracket stroke width.
- tip_len¶
Vertical tick length at each bracket end.
- y_offset¶
Extra upward pixel shift (stacks multiple brackets).
Financial Series¶
- class glyphx.candlestick.CandlestickSeries(dates: list, open: list[float], high: list[float], low: list[float], close: list[float], up_color: str = '#26a641', down_color: str = '#d73027', candle_width: float = 0.6, label: str | None = None)[source]¶
Bases:
BaseSeriesOHLC candlestick chart.
- Parameters:
dates – X-axis labels (e.g. date strings or numbers).
open – Opening prices.
high – High prices.
low – Low prices.
close – Closing prices.
up_color – Fill color when close ≥ open (bullish).
down_color – Fill color when close < open (bearish).
candle_width – Fraction of the available slot width (0–1).
label – Legend label.
- class glyphx.waterfall.WaterfallSeries(labels: list[str], values: list[float | None], up_color: str = '#2ca02c', down_color: str = '#d62728', total_color: str = '#1f77b4', bar_width: float = 0.6, connector: bool = True, show_values: bool = True, label: str | None = None)[source]¶
Bases:
BaseSeriesWaterfall (bridge) chart.
- Parameters:
labels – Category labels.
values – Deltas to add at each step. Pass
Nonefor the last bar to auto-compute the running total.up_color – Fill for positive bars.
down_color – Fill for negative bars.
total_color – Fill for the auto-total bar.
bar_width – Fraction of slot width used by each bar (0–1).
connector – Draw dashed connector lines between bars.
show_values – Print the delta value above each bar.
label – Legend label.
Hierarchical Series¶
- class glyphx.treemap.TreemapSeries(labels: list[str], values: list[float], colors: list[str] | None = None, cmap: str = 'viridis', padding: float = 2.0, show_values: bool = True, min_font: int = 9, label: str | None = None)[source]¶
Bases:
objectSquarified treemap.
- Parameters:
labels – Category labels.
values – Numeric values (determines rectangle area).
colors – Per-label colors; if
None, usescmap.cmap – Colormap name used when
colorsis not supplied.padding – Gap between rectangles in pixels.
show_values – Overlay the numeric value in each rectangle.
min_font – Minimum font size; hides label if rect too small.
label – Legend label (unused but kept for API consistency).
- class glyphx.sunburst.SunburstSeries(labels: list[str], parents: list[str], values: list[float], colors: list[str] | None = None, cmap: str = 'viridis', inner_radius: float = 40.0, ring_width: float = 60.0, padding_angle: float = 1.0, show_labels: bool = True, min_label_arc: float = 14.0, label: str | None = None)[source]¶
Bases:
objectMulti-ring sunburst chart.
The root node (parent ==
"") is drawn as the centre circle. Each subsequent ring represents one level of the hierarchy.- Parameters:
labels – Node labels (unique identifiers).
parents – Parent label for each node. Root node has
"".values – Numeric value for each leaf node. Internal nodes can be 0 - their size is auto-summed from children.
colors – Per-label hex colors. If
None,cmapis used.cmap – Colormap for auto-coloring (default
"viridis").inner_radius – Inner radius of the first ring (default 40 px).
ring_width – Width of each ring in pixels (default 60).
padding_angle – Gap between segments in degrees (default 1.0).
show_labels – Render text inside each segment.
min_label_arc – Minimum arc length in px to show a label.
label – Legend label (unused but kept for API consistency).
Streaming¶
- class glyphx.streaming.StreamingSeries(max_points: int = 100, color: str | None = None, label: str | None = None, line_width: float = 2.0, show_points: bool = False)[source]¶
Bases:
BaseSeriesSliding-window line series for real-time / streaming data.
- Parameters:
max_points – Maximum number of data points kept in the window.
color – Line color.
label – Legend label.
line_width – Stroke width.
show_points – Draw a dot at each data point.
- live(fig: object, fps: float = 10.0) _LiveContext[source]¶
Context manager for live display in Jupyter.
Usage:
with stream.live(fig, fps=10) as s: for value in sensor_generator(): s.push(value)
- Parameters:
fig – The
Figurecontaining this series.fps – Target frames per second (throttles re-renders).
- Returns:
Context manager that yields
self.
- push(value: float) StreamingSeries[source]¶
Append a new value to the stream.
Updates
self.xandself.yso the parent Figure re-renders correctly on the nextfig.render_svg()call.Returns
selffor chaining:stream.push(42.0).push(43.5)
- Parameters:
value – New data value.
- push_many(values: list[float] | ndarray) StreamingSeries[source]¶
Push multiple values at once. Returns
self.
- reset() StreamingSeries[source]¶
Clear the buffer and reset the tick counter. Returns
self.
Advanced 2-D Series¶
- class glyphx.bubble.BubbleSeries(x, y, size, color: str | None = None, c=None, cmap: str = 'viridis', alpha: float = 0.65, min_radius: float = 4.0, max_radius: float = 40.0, labels: list | None = None, label: str | None = None, stroke: str = '#ffffff', stroke_width: float = 0.8, title: str | None = None)[source]¶
Bases:
BaseSeriesScatter plot with circle area encoding a fourth variable.
Unlike
ScatterSeries(size=fixed_int), this accepts a per-point size array and scales radii so the smallest bubble is alwaysmin_radiuspixels and the largest ismax_radiuspixels.- Parameters:
x – X-axis values.
y – Y-axis values.
size – Per-point numeric values mapped to bubble area. Can also be a fixed scalar to get uniform-sized bubbles without the colormap overhead.
color – Flat fill color, or
Nonewhenc=is used.c – Per-point values for color encoding (colormap).
cmap – Colormap name (default
"viridis").alpha – Fill opacity 0–1 (default
0.65).min_radius – Pixel radius of the smallest bubble (default 4).
max_radius – Pixel radius of the largest bubble (default 40).
labels – Per-point tooltip labels (list of str).
label – Legend label for the series.
stroke – Bubble outline color (default
"#fff").stroke_width – Bubble outline width in pixels (default
0.8).
- class glyphx.parallel_coords.ParallelCoordinatesSeries(data, axes: list[str], hue: list | None = None, cmap: str = 'viridis', colors: dict | list | None = None, alpha: float = 0.45, line_width: float = 1.2, show_axes: bool = True, label: str | None = None)[source]¶
Bases:
objectParallel coordinates plot for high-dimensional data.
- Parameters:
data – 2-D array-like (rows × variables).
axes – Column / variable names (length must match data columns).
hue – Per-row group labels for color coding. When provided, each unique value gets a distinct color from the theme or
cmap. Pass a numeric array to use a continuous colormap instead.cmap – Colormap name used when
hueholds numeric values, or whencolorsis not supplied (default"viridis").colors – Explicit hex color per unique
huegroup (dict or list).alpha – Line opacity 0–1 (default 0.45). Lower values help with overplotting.
line_width – Stroke width (default 1.2).
show_axes – Draw vertical axis lines and tick labels (default True).
label – Legend label (unused but kept for API consistency).
- class glyphx.diverging_bar.DivergingBarSeries(categories: list[str], values: list[float], pos_color: str = '#2563eb', neg_color: str = '#dc2626', bar_height: float = 0.65, show_values: bool = True, zero_line: bool = True, label: str | None = None)[source]¶
Bases:
objectHorizontal diverging bar chart.
- Parameters:
categories – Category labels (one per bar, rendered on Y axis).
values – Numeric values. Positive → right; negative → left.
pos_color – Fill color for positive bars (default blue).
neg_color – Fill color for negative bars (default red).
bar_height – Fraction of available row height used by each bar (0–1).
show_values – Render the numeric value at the end of each bar.
zero_line – Draw a vertical reference line at zero.
label – Legend label.
- class glyphx.grouped_bar.GroupedBarSeries(groups: list, categories: list, values: list[list[float]], group_colors: list[str] | None = None, bar_width: float = 0.8, label: str | None = None)[source]¶
Bases:
BaseSeriesGrouped bar chart: for each category on the X-axis, draws one bar per group side-by-side, each with a distinct color.
- Parameters:
groups – Category labels shown on the X-axis (outer grouping).
categories – Series / group names (inner grouping - one bar per name).
values – 2-D list
values[group_i][cat_j].group_colors – Color per category (inner group). Auto-assigned if None.
bar_width – Fraction of the available slot used by all bars together (0–1).
label – Legend label (unused; individual category labels shown instead).
- class glyphx.swarm_plot.SwarmPlotSeries(data, categories=None, color='#1f77b4', size=4, jitter=6, label=None)[source]¶
Bases:
BaseSeriesCategorical scatter that offsets overlapping points sideways.
- Parameters:
- class glyphx.count_plot.CountPlotSeries(data, order=None, color='#1f77b4', bar_width=0.8, label=None)[source]¶
Bases:
BaseSeriesBar chart of how often each category appears.
Counts the values itself, so it takes the raw column rather than pre-aggregated totals.
- zero_anchored = True¶
Bar chart of how often each category occurs.
3-D Series¶
- class glyphx.scatter3d.Scatter3DSeries(x, y, z, color: str = '#2563eb', c: list | None = None, cmap: str = 'viridis', size: float = 5.0, label: str | None = None, alpha: float = 0.85)[source]¶
Bases:
object3D scatter plot.
- Parameters:
x – Data coordinates (same length).
y – Data coordinates (same length).
z – Data coordinates (same length).
color – Flat hex fill color when
cis not used.c – Per-point numeric values for colormap encoding.
cmap – Colormap name (default
"viridis").size – Marker size in pixels / Three.js units.
label – Legend / tooltip label.
alpha – Point opacity 0–1.
- class glyphx.surface3d.Surface3DSeries(x, y, z, cmap: str = 'viridis', alpha: float = 0.9, wireframe: bool = True, wire_color: str = '#ffffff44', label: str | None = None)[source]¶
Bases:
object3D surface plot - z = f(x, y) over a regular grid.
- Parameters:
x – 1-D X grid values (length N).
y – 1-D Y grid values (length M).
z – 2-D Z matrix, shape (M, N).
z[j][i]is the height at(x[i], y[j]).cmap – Colormap name (default
"viridis").alpha – Surface opacity 0–1.
wireframe – If
True, draw grid lines over the surface.wire_color – Color of wireframe lines.
label – Legend / tooltip label.
- class glyphx.line3d.Line3DSeries(x, y, z, color: str = '#dc2626', width: float = 2.0, linestyle: str = 'solid', label: str | None = None)[source]¶
Bases:
object3D line chart - a connected polyline through 3D coordinates.
- Parameters:
x – Path coordinates (same length, connected in order).
y – Path coordinates (same length, connected in order).
z – Path coordinates (same length, connected in order).
color – Line color.
width – Stroke width in pixels.
linestyle –
"solid","dashed","dotted".label – Legend label.
- class glyphx.bar3d.Bar3DSeries(x, y, z, dx: float | None = None, dy: float | None = None, cmap: str = 'viridis', alpha: float = 0.85, label: str | None = None)[source]¶
Bases:
object3D bar chart - one rectangular bar per (x, y) grid cell, height = z.
- Parameters:
x – 1-D X positions (bar centres).
y – 1-D Y positions (bar centres).
z – 2-D Z matrix (heights), shape (len(y), len(x)), or 1-D if x and y are already paired point arrays.
dx – Bar width along X (default: auto from grid spacing).
dy – Bar depth along Y (default: auto from grid spacing).
cmap – Colormap name for bar colours (mapped by height).
alpha – Bar opacity.
label – Legend label.
- to_svg(cam: Camera3D, x_range, y_range, z_range) str[source]¶
Project every bar to screen space and draw it back to front.
Bars are sorted by camera depth before drawing, because SVG has no z-buffer: whatever is painted last ends up on top, so far bars have to go down first or near ones get hidden behind them.
- class glyphx.contour.ContourSeries(x, y, z, levels: int | list[float] = 10, cmap: str = 'viridis', filled: bool = True, lines: bool = True, line_color: str = '#ffffff88', line_width: float = 0.8, alpha: float = 0.85, label: str | None = None)[source]¶
Bases:
BaseSeries2D filled contour plot - iso-lines and/or filled bands.
- Parameters:
x – 1-D X grid values (length N).
y – 1-D Y grid values (length M).
z – 2-D Z matrix, shape (M, N).
levels – Number of contour levels, or an explicit list of Z values.
cmap – Colormap for fill bands.
filled – Draw filled colour bands between levels.
lines – Draw contour lines at each level.
line_color – Color for contour lines when not filled.
line_width – Contour line stroke width.
alpha – Fill opacity.
label – Legend label.
Downsampling¶
GlyphX data downsampling utilities.
SVG performance degrades visibly above ~5 000 points. GlyphX automatically downsamples before SVG generation using a suite of algorithms chosen per series type.
Algorithm summary:
2-D line series : Two-stage pipeline, M4 then LTTB.
2-D scatter series: 2-D voxel grid thinning.
3-D line series : LTTB on vectorised camera-projected screen coords,
result cached in a WeakKeyDictionary keyed on camera
state + data fingerprint.
3-D scatter series: 3-D voxel grid thinning.
3-D surface series: Per-axis grid decimation + sub-pixel face culling.
Performance notes – all hot paths are fully vectorised with NumPy:
LTTB : triangle-area computation uses slice broadcasting per bucket;
no Python loop inside the bucket scan.
M4 : column assignment via np.digitize; min/max/first/last per
column via np.minimum.reduceat / np.maximum.reduceat after a
single argsort by column - no per-column Python list.
Voxel : nearest-centroid selection via np.minimum.reduceat after
sorting by cell_id - avoids a full argsort on distance.
Global kill-switch¶
Call glyphx.downsample.disable() to turn off all downsampling.
The flag lives in a threading.local so threads are independent.
Per-series control¶
Pass threshold=N to LineSeries or ScatterSeries, or set
series.threshold afterwards, to override AUTO_THRESHOLD.
Downsampling metadata¶
After rendering each series exposes series.last_downsample_info
- a dict with keys algorithm, original_n, thinned_n.
- glyphx.downsample.cull_faces(faces: list[tuple], min_area: float = 0.5) list[tuple][source]¶
Remove projected quad faces whose screen area is below
min_areapx^2.Fully vectorised NumPy shoelace computation.
- glyphx.downsample.decimate_grid(x_1d: list | ndarray, y_1d: list | ndarray, z_mat: list[list[float]] | ndarray, max_faces: int = 5000) tuple[ndarray, ndarray, ndarray][source]¶
Reduce a regular Surface3D grid by subsampling rows and columns.
Uses independent per-axis step sizes proportional to grid aspect ratio.
- Raises:
ValueError – If z_mat shape does not match (len(y_1d), len(x_1d)).
- glyphx.downsample.lttb(x: list | ndarray, y: list | ndarray, threshold: int) tuple[ndarray, ndarray][source]¶
Largest-Triangle-Three-Buckets downsampling (Steinarsson 2013).
The per-bucket triangle-area scan is vectorised: for each bucket the areas of all candidate points are computed as a NumPy slice expression and
np.argmaxselects the winner - no Python loop inside the bucket.- Parameters:
x – X values (1-D, numeric).
y – Y values (1-D, numeric, same length as x).
threshold – Maximum number of output points (>= 3).
- Returns:
(x_down, y_down)– NumPy arrays of length <= threshold.- Raises:
ValueError – If lengths differ or threshold < 3.
- glyphx.downsample.lttb_3d(x: list | np.ndarray, y: list | np.ndarray, z: list | np.ndarray, cam: Camera3D, threshold: int = 5000) tuple[np.ndarray, np.ndarray, np.ndarray][source]¶
LTTB for a 3-D polyline in screen space.
Projects via vectorised NumPy transform, then runs the vectorised LTTB inner loop on screen coordinates. Result cached in a WeakKeyDictionary keyed on (camera-state, data-fingerprint).
Respects the thread-local kill-switch.
- Raises:
ValueError – If x, y, z have different lengths.
- glyphx.downsample.m4(x: list | ndarray, y: list | ndarray, pixel_width: int) tuple[ndarray, ndarray][source]¶
M4 downsampling (Jugel et al. 2014).
Fully vectorised: column assignment uses
np.digitize; per-column first/last/min/max are found withnp.minimum.reduceatandnp.maximum.reduceatafter a single argsort by column - no per-column Python list or loop.Requires monotone X values. Non-monotone input is auto-sorted with a
UserWarning.- Parameters:
x – X values (1-D, numeric, monotone).
y – Y values (1-D, numeric, same length as x).
pixel_width – Canvas width in pixels.
- Returns:
(x_down, y_down)– NumPy arrays.
- glyphx.downsample.maybe_downsample(x: list | ndarray, y: list | ndarray, threshold: int = 5000) tuple[list | ndarray, list | ndarray][source]¶
Backward-compatible wrapper: LTTB only, no pixel width, no M4.
Deprecated since version Use:
maybe_downsample_lineinstead.
- glyphx.downsample.maybe_downsample_line(x: list | ndarray, y: list | ndarray, pixel_width: int = 800, threshold: int = 5000, m4_threshold: int = 50000) tuple[ndarray | list, ndarray | list][source]¶
Two-stage downsampling pipeline for ordered 2-D line data.
Stage 1 – M4 : if n >
m4_threshold, reduce via M4. Stage 2 – LTTB: if still >threshold, apply LTTB.Respects the thread-local kill-switch.
- glyphx.downsample.voxel_thin_2d(x: list | ndarray, y: list | ndarray, c: list | ndarray | None = None, max_points: int = 5000) tuple[ndarray, ndarray, ndarray | None][source]¶
2-D voxel grid thinning for unordered scatter data.
For each occupied grid cell keeps the point nearest to the cell centroid. Uses
np.minimum.reduceatafter sorting by cell_id to find the nearest point per cell without a full distance argsort, reducing the dominant cost from O(n log n) to O(n log n) sort by cell + O(n) scan.The dtype of
cis preserved in the output.Respects the thread-local kill-switch.
- Parameters:
x – Coordinates (1-D, same length).
y – Coordinates (1-D, same length).
c – Optional per-point values (threaded through).
max_points – Target maximum output points.
- Returns:
(x_thin, y_thin, c_thin)- Raises:
ValueError – If x and y have different lengths.
- glyphx.downsample.voxel_thin_3d(x: list | ndarray, y: list | ndarray, z: list | ndarray, colors: list | None = None, max_points: int = 5000) tuple[ndarray, ndarray, ndarray, list | None][source]¶
3-D voxel grid thinning for unordered scatter data.
Uses
np.minimum.reduceatafter sorting by cell_id to find the nearest-centroid point per voxel without a full distance argsort.Respects the thread-local kill-switch.
- Raises:
ValueError – If x, y, z have different lengths.
Note
maybe_downsample() is deprecated; use maybe_downsample_line() instead.
DataFrame Accessor¶
- class glyphx.accessor.GlyphXAccessor(df: DataFrame)[source]¶
Bases:
objectPandas DataFrame accessor that exposes the full GlyphX plotting API.
Registered automatically when
glyphxis imported. Access viadf.glyphx.<method>(...).All methods return a
Figureso results can be further customised via method chaining.- bar(x: str | None = None, y: str | None = None, color: str | None = None, label: str | None = None, yerr: str | None = None, groupby: str | None = None, hue: str | None = None, agg: str = 'sum', **kwargs: Any)[source]¶
Create a bar chart from DataFrame columns.
Pass
groupbyorhueto create one series per unique group, each colored automatically from the theme palette.huesplits by a column while keeping x/y semantics;groupbyaggregates.- Returns:
- box(col: str | None = None, groupby: str | None = None, color: str | None = None, **kwargs: Any)[source]¶
Create a box plot. Pass
groupbyfor multi-box comparison. ReturnsFigure.
- donut(labels: str | None = None, values: str | None = None, **kwargs: Any)[source]¶
Create a donut chart. Returns
Figure.
- heatmap(**kwargs: Any)[source]¶
Create a heatmap from the DataFrame’s numeric values.
The entire numeric portion of the DataFrame is treated as a 2-D matrix. Column names become column labels; index values become row labels.
- Returns:
- hist(col: str | None = None, bins: int = 10, color: str | None = None, label: str | None = None, **kwargs: Any)[source]¶
Create a histogram of a numeric column. Returns
Figure.
- line(x: str | None = None, y: str | None = None, color: str | None = None, label: str | None = None, linestyle: str = 'solid', yerr: str | None = None, **kwargs: Any)[source]¶
Create a line chart from DataFrame columns.
- Parameters:
x – Column name for X axis.
y – Column name for Y axis.
yerr – Column name for Y error bars (optional).
label – Legend label; defaults to the
ycolumn name.
- Returns:
Figure- fully chainable.
- pie(labels: str | None = None, values: str | None = None, **kwargs: Any)[source]¶
Create a pie chart. Returns
Figure.
- plot(kind: str = 'line', x: str | None = None, y: str | None = None, **kwargs: Any)[source]¶
Unified entry point - mirrors
glyphx.plot()but operates on the DataFrame’s columns.- Parameters:
kind – Chart type (same values as
glyphx.plot()).x – Column name for X axis (used for line/bar/scatter).
y – Column name for Y axis (used for line/bar/scatter).
- Returns:
- scatter(x: str | None = None, y: str | None = None, color: str | None = None, label: str | None = None, size: int = 5, marker: str = 'circle', **kwargs: Any)[source]¶
Create a scatter plot from DataFrame columns. Returns
Figure.
- stacked_bar(x: str, y: str, stack: str, normalize: bool = False, bar_width: float = 0.75, **kwargs: Any)[source]¶
Stacked bar chart from a long-format DataFrame.
Pivots
stackinto one sub-series per distinct value, summingywithin each (x,stack) pair.Negative values are supported: positive segments stack upward from zero and negative segments stack downward, so a category holding a mix shows both without the two cancelling out.
- Parameters:
x (str) – Column holding the category for each bar.
y (str) – Column holding the numeric value.
stack (str) – Column whose distinct values become stack segments.
normalize (bool) – Scale each bar to 100%. Shares are computed from absolute values, so a bar holding +5 and -5 shows +50% and -50% rather than dividing by a zero total.
bar_width (float) – Fraction of the slot each bar fills.
- Returns:
The rendered figure.
- Return type:
Example:
df.glyphx.stacked_bar(x="quarter", y="revenue", stack="segment")
Colormaps¶
- glyphx.colormaps.apply_colormap(value: float, cmap: str | list[str] = 'viridis') str[source]¶
Map a scalar in
[0, 1]to a hex color string.- Parameters:
value – Normalised value between 0 and 1.
cmap – Colormap name or a custom list of hex stops.
- Returns:
Hex color string (e.g.
"#3b528b").
- glyphx.colormaps.colormap_colors(cmap: str, n: int) list[str][source]¶
Sample
nevenly-spaced colors from a colormap.- Parameters:
cmap – Colormap name.
n – Number of colors to return.
- Returns:
List of hex color strings.
- glyphx.colormaps.get_colormap(name: str) list[str][source]¶
Return the hex color stops for a named colormap.
- Parameters:
name – Colormap name (case-insensitive).
- Raises:
ValueError – If the name is not recognised.
- glyphx.colormaps.render_colorbar_svg(cmap: str | list[str], vmin: float, vmax: float, x: float, y: float, width: float, height: float, font: str = 'sans-serif', text_color: str = '#000', steps: int = 24) str[source]¶
Generate an SVG colorbar strip with min/max labels.
- Parameters:
cmap – Colormap name or stops list.
vmin – Data range.
vmax – Data range.
x – Top-left corner of the bar in SVG units.
y – Top-left corner of the bar in SVG units.
width – Width of the color strip.
height – Height of the color strip.
font – Font family for labels.
text_color – Label fill color.
steps – Number of gradient rectangles.
- Returns:
SVG markup string.
Accessibility¶
- glyphx.a11y.generate_alt_text(fig: Figure) str[source]¶
Generate a plain-English description of a Figure for screen readers.
The description covers chart type, title, axis labels, series count, data ranges, and notable values (min / max).
- Parameters:
fig – A GlyphX
Figureinstance.- Returns:
A human-readable string suitable for
aria-labelor<desc>.
- glyphx.a11y.inject_aria(svg: str, title: str, desc: str, chart_id: str) str[source]¶
Inject ARIA attributes and landmark elements into a rendered SVG string.
Changes made:
Adds
role="img"andaria-labelledbyto the root<svg>(only if not already present)Injects
<title>and<desc>as the first children of the SVGAdds
tabindex="0"androle="graphics-symbol"to every.glyphx-pointelement for keyboard navigation
- Parameters:
svg – Raw SVG string from
Figure.render_svg().title – Short label (goes in
<title>).desc – Longer description (goes in
<desc>).chart_id – Unique chart ID already present on the
<svg>element.
- Returns:
The accessibility-enhanced SVG string.
Themes¶
- glyphx.themes.themes = {'colorblind': {'axis_color': '#000000', 'background': '#ffffff', 'colors': ['#E69F00', '#56B4E9', '#009E73', '#F0E442', '#0072B2', '#D55E00', '#CC79A7', '#000000'], 'font': 'sans-serif', 'grid_color': '#bbbbbb', 'text_color': '#000000'}, 'dark': {'axis_color': '#cccccc', 'background': '#1e1e1e', 'colors': ['#8ecae6', '#ffb703', '#219ebc', '#fb8500', '#d62828', '#a8dadc', '#f4a261', '#e9c46a'], 'font': 'sans-serif', 'grid_color': '#444444', 'text_color': '#ffffff'}, 'default': {'axis_color': '#333', 'background': '#ffffff', 'colors': ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f'], 'font': 'sans-serif', 'grid_color': '#ddd', 'text_color': '#000000'}, 'monochrome': {'axis_color': '#111111', 'background': '#ffffff', 'colors': ['#111111', '#333333', '#555555', '#777777', '#999999', '#bbbbbb', '#dddddd'], 'font': 'sans-serif', 'grid_color': '#cccccc', 'text_color': '#000000'}, 'ocean': {'axis_color': '#023e8a', 'background': '#f0f8ff', 'colors': ['#03045e', '#0077b6', '#00b4d8', '#90e0ef', '#caf0f8', '#48cae4', '#023e8a', '#0096c7'], 'font': 'sans-serif', 'grid_color': '#caf0f8', 'text_color': '#03045e'}, 'pastel': {'axis_color': '#444444', 'background': '#f9f9f9', 'colors': ['#aec7e8', '#ffbb78', '#98df8a', '#ff9896', '#c5b0d5', '#c49c94', '#f7b6d2', '#c7c7c7'], 'font': 'sans-serif', 'grid_color': '#cccccc', 'text_color': '#222222'}, 'warm': {'axis_color': '#5c3317', 'background': '#fff8f0', 'colors': ['#e63946', '#f4a261', '#e9c46a', '#2a9d8f', '#264653', '#a8dadc', '#457b9d', '#1d3557'], 'font': 'Georgia, serif', 'grid_color': '#f0d9c8', 'text_color': '#3e1f00'}}¶
Mapping of theme name to theme definition. Each value is a dict with the keys listed above; pass a name to
Figure(theme=...)orset_theme().
- glyphx.themes.register_theme(name: str, base: str = 'default', **overrides) dict[source]¶
Register a named theme so it can be used anywhere a name is accepted.
Custom themes work with
Figure(theme=...),df.glyphx.*,facet_plot,clustermap,Figure3Dand the CLI – all of which take a theme name, which previously meant a custom palette could only be used by passing a dict toFigure.set_theme()and nowhere else.- Parameters:
name – Name to register under. Must not collide with a built-in.
base – Existing theme to inherit unspecified keys from.
**overrides – Any of
colors,axis_color,grid_color,font,background,text_color.
- Returns:
The fully resolved theme, also stored in the registry.
- Return type:
- Raises:
ValueError – On a built-in name, an unknown base, an unknown key, or a malformed
colorsvalue.
Example:
from glyphx import Figure, register_theme register_theme( "acme", base="dark", colors=["#e6194b", "#3cb44b", "#4363d8"], font="Inter, sans-serif", ) Figure(theme="acme").line(x, y).show()
- glyphx.themes.unregister_theme(name: str) None[source]¶
Remove a custom theme. Built-ins cannot be removed.
- Raises:
ValueError – If
nameis a built-in.KeyError – If
nameis not registered.
- glyphx.themes.get_theme(spec=None) dict[source]¶
Resolve a theme name or dict into a complete theme dictionary.
- Parameters:
spec – A registered theme name, a partial theme dict (missing keys are filled from
"default"), orNonefor the default.- Returns:
A theme with every key in
THEME_KEYSpopulated.- Return type:
- Raises:
ValueError – If the name is not registered, or the dict is malformed. Previously an unknown name fell back to
"default"silently, so a typo liketheme="darkk"rendered a light chart with no indication anything was wrong.
Tick label wrapping¶
- glyphx.utils.wrap_tick_label(label, max_chars, max_lines: int = 2) list[source]¶
Word-wrap a tick label to at most
max_lineslines of roughlymax_charscharacters each.Character-count based, like every other width estimate in this codebase – SVG text has no font-metrics API to query, so
Axes._should_rotate_xlabelsuses the same kind of estimate for its rotate-vs-not decision. This is the wrap alternative: a label too long to fit at the current tick spacing goes to two lines instead of forcing every label on the axis to rotate.A single word longer than
max_charsis hard-split rather than left to overflow one line. If content remains aftermax_lines, the last line is truncated with an ellipsis rather than silently dropped.
Available theme names: "default", "dark", "colorblind",
"pastel", "warm", "ocean", "monochrome"
Utilities¶
- glyphx.utils.normalize(data)[source]¶
Normalize a numeric array to the [0, 1] range.
- Parameters:
data (array-like) – List or NumPy array of values.
- Returns:
Values scaled to [0, 1].
- Return type:
np.ndarray
- Raises:
ValueError – If all values are equal (zero-width range).
- glyphx.utils.svg_escape(text)[source]¶
Escape a string so it is safe inside SVG text or an attribute.
- glyphx.utils.wrap_svg_canvas(svg_content: str, width: int = 640, height: int = 480, has_math: bool = False, crossfilter: bool = False, axis_metadata: str = '') str[source]¶
Wrap raw SVG elements in a full <svg> root element.
The chart id is a hash of the SVG content and canvas size, so the same figure always renders byte-identical output. A UUID would be equally collision-resistant, but it made every render differ from the last – which defeats caching, makes diffs unreadable, and rules out golden-file tests. Distinct charts still get distinct ids because distinct content hashes differently.
- Parameters:
svg_content (str) – Inner SVG markup.
width (int) – Canvas width in pixels.
height (int) – Canvas height in pixels.
has_math (bool) – When True, embeds a MathJax data attribute so wrap_svg_with_template injects the CDN script.
crossfilter (bool) – When True, marks the root so crossfilter.js includes this chart. Charts without the marker are left alone, so one page can mix filtered and independent charts.
- Returns:
Complete SVG document string.
- Return type:
Build a fully self-contained HTML document with all JavaScript inlined.
The output has zero external dependencies and renders correctly in: - Email clients (tested in Gmail, Outlook web) - Confluence / Notion embeds - GitHub Pages / static hosts - Air-gapped / offline environments
- glyphx.utils.write_svg_file(svg_string: str, filename: str, **kwargs)[source]¶
Save a chart to file.
.svgand.htmlare written directly..png,.jpg,.webp, and.pdfare delegated toglyphx.export, which picks whichever rendering backend is installed.- Parameters:
- Raises:
RuntimeError – If no backend can produce the requested format.
Projection (3-D)¶
- class glyphx.projection3d.Camera3D(azimuth: float = 45.0, elevation: float = 30.0, cx: float = 0.0, cy: float = 0.0, scale: float = 1.0)[source]¶
Bases:
objectOrthographic camera for projecting 3D data to 2D SVG.
- Angles follow the geographic convention:
- azimuth - rotation around the vertical (Z) axis, degrees.
0° = looking from +Y; 90° = looking from +X.
- elevation - tilt above the horizontal plane, degrees.
0° = side view; 90° = top-down.
- The right-hand coordinate system uses:
X → right, Y → into screen (depth), Z → up.
Additional Chart Types (v1.6+)¶
- class glyphx.gantt.GanttSeries(tasks: list[dict[str, Any]], group_colors: dict[str, str] | None = None, cmap: str = 'viridis', bar_height: int = 20, row_padding: int = 6, show_today: bool = True, today_color: str = '#ef4444', show_grid: bool = True, label: str | None = None)[source]¶
Bases:
BaseSeriesGantt / project timeline chart.
Each task is one horizontal bar spanning from
starttoend. Milestones (single-day events with"milestone": True) are rendered as diamond markers instead of bars.- Parameters:
tasks –
List of task dicts, each with keys:
"task"(str) – display label"start"(date|str) – bar left edge"end"(date|str) – bar right edge"group"(str, optional) – colour group"milestone"(bool, optional) – diamond marker"tooltip"(str, optional) – custom tooltip text"progress"(float 0-1, optional) – fill fraction
group_colors –
{group_name: hex_color}mapping. Auto-assigned fromcmapif not provided.cmap – Colormap for auto-assigned group colours.
bar_height – Pixel height of each task bar (default 18).
row_padding – Pixel gap between task rows (default 6).
show_today – Draw a vertical line at today’s date.
today_color – Color of the today marker.
show_grid – Draw vertical date-grid lines.
label – Series legend label.
- class glyphx.stacked_bar.StackedBarSeries(x: list, series: dict[str, list[float]], colors: list[str] | None = None, normalize: bool = False, bar_width: float = 0.75, label: str | None = None)[source]¶
Bases:
BaseSeriesBars split into stacked segments, optionally normalised to 100%.
Each key in
stacksbecomes one segment layer across every category, drawn bottom-up in insertion order.- to_svg(ax: AxesLike, use_y2: bool = False) str[source]¶
Draw each category’s bar as a run of segments stacked from the baseline.
- zero_anchored = True¶
Stacked bar chart - multiple series stacked vertically per category.
- Parameters:
x – Category labels for the X-axis.
series –
{label: [values]}mapping. Order determines stack order (first key is at the bottom).colors – Per-series hex colors. Falls back to the active theme palette.
normalize – If
True, bars are normalized to 100% (proportional stacking).bar_width – Fraction of the available slot width per bar (0–1).
label – Legend label (not used; each sub-series has its own label).
- class glyphx.bump_chart.BumpChartSeries(x: list, rankings: dict[str, list[int]], colors: list[str] | None = None, line_width: float = 3.0, dot_radius: float = 6.0, show_labels: bool = True, label: str | None = None)[source]¶
Bases:
objectRank-over-time chart drawn with smooth Bézier curves.
Lower rank number = higher position (rank 1 is at the top).
- Parameters:
x – Time-axis labels (columns).
rankings –
{series_name: [rank_at_each_x]}mapping.colors – Per-series colors. Auto-assigned if None.
line_width – Stroke width of each ribbon.
dot_radius – Radius of the rank-position dots.
show_labels – Draw series name at leftmost and rightmost position.
label – Legend label (unused; individual series labeled directly).
- class glyphx.sparkline.SparklineSeries(data: list[float], color: str = '#2563eb', kind: str = 'line', fill: bool = True, fill_alpha: float = 0.18, line_width: float = 1.5, show_last_dot: bool = True, label: str | None = None)[source]¶
Bases:
BaseSeriesLightweight sparkline series. Designed for very small canvases (width ≤ 200, height ≤ 60). Omits axis lines, grid, and labels.
- Parameters:
data – Numeric values.
color – Line color.
kind –
"line"or"bar".fill – Shade area under the line.
fill_alpha – Fill opacity.
line_width – Stroke width.
show_last_dot – Highlight the final data point.
label – Legend label.
- glyphx.sparkline.sparkline_svg(data: list[float], width: int = 80, height: int = 28, color: str = '#2563eb', kind: str = 'line', line_width: float = 1.5, fill: bool = True, fill_alpha: float = 0.18, show_last_dot: bool = True, padding: int = 2) str[source]¶
Render a compact sparkline and return raw SVG markup.
- Parameters:
data – Numeric values to plot.
width – Pixel width of the sparkline.
height – Pixel height.
color – Line / bar fill color.
kind –
"line"or"bar".line_width – Stroke width for line sparklines.
fill – Shade area under the line.
fill_alpha – Fill opacity (0–1).
show_last_dot – Mark the last data point with a circle.
padding – Pixel margin around the chart area.
- Returns:
Complete
<svg>element as a string.
FacetGrid¶
- class glyphx.facet_grid.FacetGrid(data, col: str | None = None, row: str | None = None, hue: str | None = None, height: int = 300, aspect: float = 1.4, col_wrap: int | None = None, theme: str = 'default', sharex: bool = True, sharey: bool = True, col_order: list | None = None, row_order: list | None = None, hue_order: list | None = None, palette: list | None = None)[source]¶
Bases:
objectSmall-multiples grid.
- Parameters:
data – Source DataFrame.
col – Column name to facet along the X axis.
row – Column name to facet along the Y axis (optional).
hue – Column name for color-coding within each cell (optional).
height – Pixel height of each cell.
aspect – Width/height ratio of each cell.
col_wrap – Wrap into a new row after this many columns.
theme – GlyphX theme name.
sharex – Share X-axis scale across all cells.
sharey – Share Y-axis scale across all cells.
col_order – Explicit ordering of column facets.
row_order – Explicit ordering of row facets.
hue_order – Explicit ordering of hue groups.
palette – Color palette for hue groups (list of hex strings).
- map(kind: str, x: str | None = None, y: str | None = None, **kwargs) FacetGrid[source]¶
Apply a chart type to each facet cell.
- Parameters:
kind – Chart kind (
"scatter","line","bar","hist","kde","box","violin").x – X-axis column name.
y – Y-axis column name (not needed for
"hist"/"kde").**kwargs – Passed to the series constructor.
- Returns:
selffor chaining.
Example:
g = FacetGrid(df, col="species", hue="island") g.map("scatter", x="bill_length", y="flipper_length") g.map("hist", x="body_mass")
Regression Plot¶
- glyphx.regplot.regplot(data, x: str | None = None, y: str | None = None, x_vals: list | None = None, y_vals: list | None = None, order: int = 1, lowess: bool = False, logistic: bool = False, ci: int = 95, n_boot: int = 100, scatter_kw: dict | None = None, line_kw: dict | None = None, color: str = '#2563eb', alpha: float = 0.2, title: str = '', theme: str = 'default', auto_display: bool = False) Figure[source]¶
Regression plot: scatter + fitted curve + optional CI band.
Supports OLS, polynomial, logistic, and LOWESS regression, all in pure NumPy. Seaborn’s
regplotrequires statsmodels for some modes; GlyphX has zero extra dependencies.- Parameters:
data – DataFrame (use with
x=andy=column names) orNone(usex_vals/y_valsdirectly).x – Column names when
datais a DataFrame.y – Column names when
datais a DataFrame.x_vals – Raw numeric arrays when
datais None.y_vals – Raw numeric arrays when
datais None.order – Polynomial degree (1 = linear, 2 = quadratic, etc.)
lowess – Use LOWESS instead of polynomial.
logistic – Fit logistic curve (binary Y assumed).
ci – Confidence interval level (0-100). 0 disables CI band.
n_boot – Bootstrap samples for the CI band.
scatter_kw – Extra kwargs for
ScatterSeries.line_kw – Extra kwargs for
LineSeries.color – Shared colour for scatter and fit line.
alpha – CI band fill opacity.
title – Chart title.
theme – GlyphX theme name.
auto_display – Open immediately after creation.
- Returns:
Figureready to.show()or.save().
Examples:
from glyphx.regplot import regplot # OLS regplot(df, x="height", y="weight") # Quadratic regplot(df, x="age", y="income", order=2, color="#dc2626") # LOWESS regplot(df, x="gdp", y="life_exp", lowess=True) # Logistic (binary outcome) regplot(df, x="dose", y="response", logistic=True) # No data frame import numpy as np x = np.random.randn(200) y = 2*x + np.random.randn(200) regplot(None, x_vals=x, y_vals=y, title="Correlation")
Choropleth Map¶
- class glyphx.choropleth.ChoroplethSeries(geojson: dict | list, data: dict[str, float], key: str = 'name', cmap: str = 'viridis', missing_color: str = '#e0e0e0', stroke: str = '#ffffff', stroke_width: float = 0.4, alpha: float = 0.9, label: str | None = None, title: str | None = None)[source]¶
Bases:
objectSVG-path choropleth map from GeoJSON.
No tiles, no CDN – renders as pure SVG paths projected via Mercator.
- Parameters:
geojson – GeoJSON FeatureCollection dict (
{"type":"FeatureCollection", "features":[...]}) or a list of feature dicts.data –
{feature_key: numeric_value}mapping.key – GeoJSON feature property name that matches
datakeys.cmap – Colormap name.
missing_color – Fill color for features with no matching data entry.
stroke – Border stroke color.
stroke_width – Border stroke width.
alpha – Fill opacity.
label – Legend / tooltip label.
title – Chart title (forwarded to Figure).
Clustermap¶
- glyphx.clustermap.clustermap(data, row_labels: list[str] | None = None, col_labels: list[str] | None = None, cmap: str = 'viridis', row_cluster: bool = True, col_cluster: bool = True, standard_scale: str | None = None, z_score: str | None = None, show_values: bool = False, figsize: tuple[int, int] = (720, 640), title: str = '', dendrogram_ratio: float = 0.15, line_color: str = '#555', theme: str = 'default') Figure[source]¶
Hierarchically clustered heatmap with row and column dendrograms.
Equivalent to
seaborn.clustermap()but implemented in pure NumPy – no scipy, no matplotlib required.- Parameters:
data – 2-D numeric array or pandas DataFrame.
row_labels – Labels for rows (inferred from DataFrame index if None).
col_labels – Labels for columns (inferred from DataFrame columns if None).
cmap – Colormap name (default
"viridis").row_cluster – Cluster and reorder rows (default True).
col_cluster – Cluster and reorder columns (default True).
standard_scale –
"row"or"col"– scale each row/column to [0,1].z_score –
"row"or"col"– z-score normalise each row/column.show_values – Overlay the numeric value in each cell.
figsize –
(width, height)in pixels.title – Chart title.
dendrogram_ratio – Fraction of figure width/height used by dendrograms.
line_color – Dendrogram line colour.
theme – GlyphX theme name.
- Returns:
Figurecontaining the clustered heatmap and dendrograms rendered as SVG.
Example:
import pandas as pd from glyphx.clustermap import clustermap df = pd.read_csv("gene_expression.csv", index_col=0) fig = clustermap(df, cmap="coolwarm", z_score="row", title="Gene Expression Heatmap") fig.show() fig.save("clustermap.html")
Vega-Lite Export¶
- glyphx.vega_lite.to_vega_lite(fig, width: int | None = None, height: int | None = None) dict[str, Any][source]¶
Convert a
Figureto a Vega-Lite v5 specification dict.The resulting specification can be:
Saved as a
.vl.jsonfile and opened in the Vega editorEmbedded in Observable notebooks
Rendered with
altair(alt.Chart.from_dict(spec))Shared as a portable, renderer-agnostic chart format
- Parameters:
fig – GlyphX
Figureinstance.width – Override canvas width (defaults to
fig.width).height – Override canvas height (defaults to
fig.height).
- Returns:
Vega-Lite v5 specification as a nested dict.
Example:
from glyphx import Figure from glyphx.series import LineSeries from glyphx.vega_lite import to_vega_lite import json fig = Figure().add(LineSeries(months, revenue, label="Revenue")) spec = to_vega_lite(fig) print(json.dumps(spec, indent=2))
Aggregation¶
Collapsing repeated measurements per x into an estimate and an interval,
which is what glyphx.Figure.aggregate_line() draws.
- glyphx.aggregate.aggregate(x_values, y_values, *, estimator='mean', ci=95, n_boot=1000, n_std=1.0, seed=42)[source]¶
Collapse repeated y values per x into an estimate and an interval.
- Parameters:
x_values – The x of each observation. Repeats are the point: every observation sharing an x forms one group.
y_values – The observed value for each.
estimator –
"mean","median","sum","min","max","count", or any callable reducing an array to a scalar.ci – Confidence level 0-100 for a bootstrap interval,
"sd"for one standard deviation,"se"for standard error, orNonefor no interval at all.n_boot – Bootstrap resamples when
ciis a number.n_std – Multiplier for the
"sd"and"se"intervals.seed – Fixed so a chart redrawn from the same data is identical – a band that shifted slightly on every render would make figures irreproducible.
- Returns:
(xs, centre, lower, upper), sorted by x.lowerandupperareNonewhenciisNone.- Return type:
- Raises:
ValueError – If the two inputs differ in length, or the estimator or ci is not recognised.
Math in labels¶
- glyphx.mathtext.render(text: str) str[source]¶
Render a label, converting any
$...$spans to SVG markup.Text outside the math spans is escaped and left alone, so mixed labels such as
"Energy $E = mc^2$ over time"work.
- glyphx.mathtext.to_plain_text(text: str) str[source]¶
Convert a label to a spoken form for alt text and ARIA descriptions.
Markup is useless to a screen reader, so
$\sigma_{x}$becomesσ_xrather than a pile of tspans.
- glyphx.mathtext.estimate_width(text: str, font_size: float) float[source]¶
Approximate the rendered width of a label in pixels.
Layout code sizes gutters and legends before anything is drawn, and a math label’s width is not its character count – scripts are smaller and commands collapse to one glyph.
Export backends¶
- glyphx.export.render_to_file(svg: str, path: str, dpi: int = 96, backend: str | None = None) str[source]¶
Rasterise
svgtopath, choosing an available backend.- Parameters:
- Returns:
The backend that produced the file.
- Return type:
- Raises:
ExportError – If the format is unsupported, or no backend can write it.
PDF writer¶
The pure-Python PDF backend. It needs nothing beyond the standard library,
which is why .pdf works in a bare virtualenv or CI container with no
system libraries and no browser.
- glyphx.pdf_writer.svg_to_pdf(svg: str, path: str) None[source]¶
Write
svgtopathas a vector PDF, using only the standard library.- Parameters:
svg – An SVG document.
path – Destination
.pdffile.
- Raises:
UnsupportedSVGError – For SVG features with no faithful PDF equivalent here – gradients, clipping, filters, embedded images. Raised rather than dropped, so the output is never quietly missing part of the chart.
- class glyphx.pdf_writer.UnsupportedSVGError[source]¶
Bases:
ValueErrorRaised for SVG this converter cannot faithfully reproduce.
Preferred over dropping the element: a PDF that silently lost a gradient or a clipped region looks complete while being wrong, and the caller has no way to notice.
pandas backend¶
Registered under the pandas_plotting_backends entry point, so
pd.options.plotting.backend = "glyphx" resolves here. Not called
directly – see glyphx.Figure.line() and the accessor below for
GlyphX’s own APIs.
- glyphx.pandas_backend.plot(data, x=None, y=None, kind: str = 'line', **kwargs: Any)[source]¶
Entry point pandas calls for
df.plot()/series.plot()and thedf.plot.line()-style accessors, oncepd.options.plotting.backend = "glyphx"is set.Not meant to be called directly – see
line()and friends, or the DataFrame accessor atglyphx.accessor, for GlyphX’s own plotting APIs.- Returns:
ready to
.show(),.share()or.save(). Also displays automatically in a notebook, the same as any other GlyphX figure – matplotlib’s backend returns anAxesinstead, which is the one difference a caller migrating existing code will notice in the return value.- Return type: