Glowbar, fluxbox and hexmatrix
Show observations, summaries and density with individually named plot parts.
Three signature plots show observations beside their summary. Each takes a table (a pandas or polars DataFrame, or a dict of columns) plus column names, seaborn-style, and names every part for you. Hover a real fluxbox on the semantic plots page to see those names. In the examples, df is your table and ax an axes.
Glowbar
gb = fp.glowbar(df, x="condition", y="APP/GAPDH", units="subject", ax=ax)
# Paired or repeated measures: connect each unit across conditions.
gb = fp.glowbar(df, x="condition", y="signal", units="mouse",
connect_identical_points_across_x_values=True, ax=ax)Every observation is a dot. Beside each group sits a slim bar that glows — its ink densest at the centre of the distribution and fading to hard caps at the interval ends — with the mean as a heavy, haloed line across the bar and the median as a V-notch cut into both of its edges. The interval is mean ± SEM by default, glowing around the mean; interval="iqr" spans the box of a box plot and glows around the median, "sd" gives mean ± SD, and a callable values -> (low, high) is accepted. Default groups use ColorBrewer’s YlGnBu, then YlOrRd.
With units= every unit (animal, subject, cell) keeps a fixed lane and colour derived from the table, never from the values, so plots of different measures made from one table agree dot for dot — even when a unit is missing from one of them. Unit colours are equal perceptual steps (CAM02-UCS) of each group’s ColorBrewer map between shade_range=(88, 22) lightness, dealt across lanes so neighbours always contrast (interleave_shades=True), and rimmed in a deeper shade of themselves so the palest dots stay crisp (point_edge="rim"). Connectors are a quiet neutral grey and break at a unit’s missing category rather than bridging it.
| Part | Role | Default ID |
|---|---|---|
| interval glow | box |
<category>.glow |
| interval caps | cap |
<category>.caps |
| mean line | mean |
<category>.mean |
| median notch | median |
<category>.median |
| a unit’s points | point |
<unit>.points, <unit>.point.<k> |
| a unit’s connector | line |
<unit>.line |
points without units |
point |
<category>.points, <category>.point.<k> |
Each category series carries a glowbar manifest payload with the exact statistics drawn (n, mean, median, sd, sem, q1, q3, interval, low, high, center, x, groupColor), and each unit series its identity (units, unit, categories, colors); the manifest’s plotType is "glowbar". Series names default to the category and unit values; series= and unit_series= (a mapping or a callable) rename them.
Every visual choice is a keyword (see fp.glowbar for all of them):
- Bar:
bar_width,bar_offset,bar_side("outer", the default, puts the first category’s bar left of its points and every other bar to the right;"left"or"right"applies to all),glow_steps,glow_alpha. - Mean, median and caps:
mean_line_width,mean_color,mean_halo_width,median_notch_depth,median_notch_height,cap_width,cap_color, and the switchesshow_mean,show_median,show_caps,show_individual_points. - Points:
point_size,jitter,point_edge,point_fill_alpha(fill only; the rim stays opaque). - Colour:
palette(per category: anyfp.colors.mapscolormap such as"cmasher.emerald", anyfp.colors.palettespalette such as"brewer.Set2"or"tol.bright", a matplotlib map, a list of colours or one colour; glowbar picks as many distinct point colours as it needs plus a solid group colour),group_color,group_color_position,point_colors,shade_range,interleave_shades. - Connectors:
connect_line_width,connect_color,connect_alpha.
It returns a GlowbarResult (.ax, .categories, .stats, .group_colors, .point_colors, .series, .unit_series, .artists). The fluxplot repository’s examples/glowbar_example.py draws both designs shown above (unpaired and paired).
Fluxbox
The fluxbox is the glowbar with a box plot for its summary — the same call, the same lanes, colours, connectors and names, so the two can be swapped for one another dot for dot:
fb = fp.fluxbox(df, x="condition", y="APP/GAPDH", units="subject", ax=ax)Beside each group sits a slim box (Q1–Q3), a half-strength wash of the group colour (box_alpha=0.5). The median is a solid line across it in the group’s own hue — deepened, or on a dark background lifted, only as far as it takes to differ from the box by median_contrast=30 units of perceived lightness, so it reads for any palette and theme; the whiskers (and fliers) share that colour, so the box is the only wash. The mean is a V-notch cut into both edges of the box — the glowbar’s median notch; a mean outside the box (a strongly skewed group) keeps its mark as the same two V’s drawn solid, pointing in at the whisker. The capless whiskers reach the most extreme observations within whis × IQR of the box (1.5 — Tukey’s rule, exactly plt.boxplot’s whiskers), "range", or a (low, high) pair of percentiles. Observations beyond the whiskers are not drawn again as fliers — the points already show them — unless the points are hidden (show_fliers="auto").
| Part | Role | Default ID |
|---|---|---|
| box (Q1–Q3) | box |
<category>.box |
| whiskers | whisker |
<category>.whiskers |
whisker caps (show_caps=True) |
cap |
<category>.caps |
| median line | median |
<category>.median |
| mean notch | mean |
<category>.mean |
| fliers (points hidden) | flier |
<category>.fliers |
| points and connectors | point, line |
as for the glowbar |
Each category series carries a fluxbox manifest payload with the exact statistics drawn (n, mean, median, sd, sem, q1, q3, iqr, whis, whiskerLow, whiskerHigh, outliers, x, groupColor); the manifest’s plotType is "fluxbox".
The box keywords are whis, box_width, box_alpha, box_offset, box_side, median_line_width, median_color (sets the median colour outright), median_contrast, mean_notch_depth, mean_notch_height, whisker_width, whisker_color, cap_size, cap_width, cap_color, flier_size, cut_color, and the switches show_mean, show_median, show_whiskers, show_caps and show_fliers. Every point, colour, connector and naming keyword is the glowbar’s. It returns a FluxboxResult with the same fields as a GlowbarResult. The fluxplot repository’s examples/fluxbox_example.py draws a complete example.
Hexmatrix
The hexmatrix tiles the plane with regular hexagons, each one a named part. One call covers a point cloud’s density, a 2D gradient of a third variable, and a matrix drawn on a hex lattice:
# Density with marginal histograms, jointplot-style:
hm = fp.hexmatrix(df, x="x", y="y", ax=ax, color="#4CB391", marginals=True)
# Log-log density with an identity line:
hm = fp.hexmatrix(df, x="wake", y="nrem", ax=ax, xscale="log", yscale="log",
norm="log", identity_line=True,
colorbar_label="Synapses per hexbin")
# Spatial density in 0.15 mm bins:
hm = fp.hexmatrix(df, x="ccf_x", y="ccf_z", ax=ax, aspect="equal", binwidth=0.15,
norm="log", colorbar_label="somata / hexbin")
# A gradient of a third variable, C:
hm = fp.hexmatrix(df, x="x", y="y", C="rate", reduce="median", ax=ax,
cmap="RdBu_r", center=0)
# A matrix drawn on a hex lattice:
hm = fp.hexmatrix(matrix=weights, ax=ax, gap=0.08)Hexagons are addressed by their lattice position: row counts up the y axis and col along x, so <series>.hex.<row>.<col> names the same hexagon in every plot with the same extent and grid, whatever the data. They are regular on the page. aspect="auto" locks the axes’ box aspect so a later layout pass can’t squash them, and aspect="equal" bins in true data units. Log axes bin in log space.
The colour can be a count, stat="density"/"probability"/"percent" (optionally weights=), or a reduce of C (mean, median, sum, min, max, std, count or a callable). The scale is set by cmap/color (a single-hue ramp), norm (linear/log/sqrt or any Normalize), vmin/vmax, robust and center. Further keywords:
mincnt=0draws the empty hexagons too;sparse=kdraws points instead of hexagons where fewer thankobservations fall;show_pointsoverlays every observation;gap,edgecolor,linewidthandorientation="flat"shape the hexagons;marginals,colorbarandidentity_lineadd furniture.
The colormap and colour limits are recipe controls, exactly as for fp.heatmap: Flux’s Colour scales editor can change them and regenerate the plot.
| Part | Role | Default ID |
|---|---|---|
| all hexagons | x-hexbin |
<series>.hexes |
| one hexagon | x-hex |
<series>.hex.<row>.<col> |
| sparse or overlaid points | point |
<series>-points.points, <series>-points.point.<k> |
| identity line | reference-line |
reference-line.identity |
| marginal histograms (own panels) | bar |
<series>-x.bar.<k>, <series>-y.bar.<k> |
Each hexagon element also carries data-row, data-column, data-x, data-y, data-count and data-value attributes.
The series carries a hexmatrix manifest payload: the lattice (orientation, radius, aspect, scales, extent), the statistic, and every hexagon drawn (row, col, x, y, count, value). It also carries the usual field colour payload; the plotType is "hexmatrix". The call returns a HexMatrixResult (.ax, .hexes, .bins, .cmap, .norm, .colorbar, .marginal_axes, .points, .hex_id(row, col), .lookup(x, y)).
Hexagons stay individually addressable up to vector_limit (5000 by default; None uses the save’s generic threshold of 800 elements). A larger layer is rasterized like any heavy layer, but its hexagons stay in the manifest; pass force_vectors=True to fp.save to keep every hexagon addressable. On axes that share x or y with other panels, fp.hexmatrix leaves the box aspect unlocked, with a warning, rather than distorting the sibling panels. The fluxplot repository’s examples/hexmatrix_example.py draws all five variants shown above.