scistackplot
Build the figure by looking at it, then keep it
scistackplot turns a long-format table into a figure from a small,
serializable description — a PlotSpec. It works standalone on a CSV or a
DataFrame with no database and no configuration, and the same PlotSpec is
exactly what the body of a SciDB plot_ endpoint needs, so an interactive
exploration can be frozen into a lineage-tracked pipeline step.
pip install scistackplot
The idea
A plotting GUI looks like it produces pictures. It doesn't — it produces a specification, and the picture is a view of it. That is what lets an inherently visual tool live inside a reproducible pipeline:
import pandas as pd
from scistackplot import DataFrameSource, PlotSpec, Role, PlotKind, render
source = DataFrameSource(pd.read_csv("gait.csv"))
spec = PlotSpec(
measures=["StepLength"],
roles={"session": Role.X, "limb": Role.COLOR, "subject": Role.FREE},
kind=PlotKind.BOX,
)
figure = render(source, spec)
Every factor does exactly one thing
The whole control surface is one rule: each categorical column carries exactly one role.
| Role | Meaning |
|---|---|
X |
x-axis position |
COLOR |
one coloured series per level |
FACET |
one subplot per level (arranged by FacetOptions) |
ITERATE |
a separate figure per level |
AGGREGATE |
collapse — average over this factor |
FREE |
keep as replicate rows |
Which plot kinds are available follows from that assignment plus the measure's shape, through one pure function:
from scistackplot import available_plots, default_plot, Shape
available_plots(Shape.SCALAR, {"session": Role.X}) # scatter, strip
available_plots(Shape.SCALAR, {"session": Role.X, "trial": Role.FREE}) # + box, violin, bar
A distribution needs replicates, and replicates exist only when some factor is
left FREE. That single rule produces both defaults and availability:
| Measure shape | no replicates | with replicates |
|---|---|---|
| scalar | scatter | box / violin / bar + CI |
| 1-D array | one line per observation | mean line + shaded error band |
| 2-D | heatmap | mean heatmap |
AGGREGATE deliberately does not count as replicates: it averages its factor
away before anything is drawn. "Average over trials, then show the spread
across subjects" is trial=AGGREGATE, subject=FREE.
Arranging the subplots
Faceted panels flow in order by default, wrapping at FacetOptions.wrap. When
the arrangement matters, describe it with rules instead of positions:
from scistackplot import FacetOptions, MatchOp, Matcher, PlotSpec, Role
spec = PlotSpec(
measures=["RawEMG"],
roles={"ColName": Role.FACET, "subject": Role.COLOR},
facet=FacetOptions(
rows=[Matcher(op=MatchOp.STARTS_WITH, value="R"),
Matcher(op=MatchOp.STARTS_WITH, value="L")],
cols=[Matcher(op=MatchOp.ENDS_WITH, value="HAM"),
Matcher(op=MatchOp.ENDS_WITH, value="TA")],
),
)
Rules describe a layout rather than a hand-arrangement, so the same
FacetOptions applies to any variable whose panels are named the same way.
Ops are starts_with, ends_with, contains, not_contains, equals and
regex; a panel matching no rule lands in a trailing "other" row or column
rather than vanishing.
Each panel is named on its y axis, not by a caption above it. A caption
spends a strip of every row of the grid on text; the axis title is room the
panel was already spending, so a 4x3 grid gets that height back for the data.
The generated seaborn code says the same thing (g.set_titles("")), because
the export must be the figure you previewed.
Ordering is not cosmetic
Zero-padded IDs ("01", "02", … "10") sort lexicographically into
1, 10, 2 under pandas' default — visibly wrong on an axis, and wrong in a way
that looks like a data problem. LongTable carries each factor's real level
order; sources that know better (SciDB knows its declared schema_key_types)
supply it explicitly, and everything else falls back to a natural sort.
Rendering
Two backends translate the same reduced plot, so the interactive view and the exported figure cannot disagree:
from scistackplot import resolve, render_matplotlib, render_plotly
resolved = resolve(spec, table) # all reduction happens here
figure = render_matplotlib(resolved[0]) # export / pipeline — a Figure
payload = render_plotly(resolved[0]) # interactive — a plotly.js dict
render_plotly builds plain JSON and needs no plotly package.
Export: real code, not a call back into this library
from scistackplot import generate_plot_function
print(generate_plot_function(spec, table))
def plot_steplength(df, filename):
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
g = sns.catplot(
data=df,
x='session',
y='StepLength',
hue='limb',
kind="box",
)
g.set_axis_labels('session', 'StepLength')
return g.figure
Your pipeline gets ordinary seaborn code it can keep, edit, and read — no runtime dependency on this package. The spec is embedded in the docstring, so the GUI can reopen a figure you have since hand-edited.
Data sources
DataSource is a three-method protocol (describe, get_table,
joinable_with). scistackplot ships CsvSource and DataFrameSource;
scistackplotdb ships the SciDB one. Anything
consuming the protocol — including the Plot Studio panel in the SciStack GUI —
works identically against a lone CSV and a full project database.
Relationship to SciDB endpoints
Recording a figure is SciDB's job and is unchanged: name a function plot_,
return a Figure, and finalized=True stores it as a queryable record with an
embedded provenance stamp. scistackplot supplies the body of that function;
scistackplotdb generates the for_each call around it.
See docs/claude/plotting-library-design.md.
Optional extras
pip install "scistackplot[mpl]" # matplotlib + seaborn (export)
pip install "scistackplot[interactive]" # plotly Figure objects
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scistackplot-0.1.26.tar.gz.
File metadata
- Download URL: scistackplot-0.1.26.tar.gz
- Upload date:
- Size: 104.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d3b93339d22d72bf6d0ef3d67576d778f98fd1339067b665afecd2832659fb2
|
|
| MD5 |
4e044f6f67fe79f24cad00d4ebe2932a
|
|
| BLAKE2b-256 |
4d32517c8d91618eb5dd314f4c242c1df3c20465a4c80c871b3df194ed9b6a19
|
Provenance
The following attestation bundles were made for scistackplot-0.1.26.tar.gz:
Publisher:
publish.yml on mtillman14/scistack
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scistackplot-0.1.26.tar.gz -
Subject digest:
4d3b93339d22d72bf6d0ef3d67576d778f98fd1339067b665afecd2832659fb2 - Sigstore transparency entry: 2818273570
- Sigstore integration time:
-
Permalink:
mtillman14/scistack@dceb1ef3ad83a0e46bca88afe94a2281e4e6dde6 -
Branch / Tag:
refs/tags/v0.1.27 - Owner: https://github.com/mtillman14
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dceb1ef3ad83a0e46bca88afe94a2281e4e6dde6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file scistackplot-0.1.26-py3-none-any.whl.
File metadata
- Download URL: scistackplot-0.1.26-py3-none-any.whl
- Upload date:
- Size: 120.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6158dec7614e3e6fb861d2cb2acd4f46cd8128bf63907e59ae938096550dc4a5
|
|
| MD5 |
8d84d05ca2c6fb50bc642039f5ce7a31
|
|
| BLAKE2b-256 |
46f821b66dcc2108f16da886fabdee31ca7c58cde7e2d5b3a13a91d2d40f8a09
|
Provenance
The following attestation bundles were made for scistackplot-0.1.26-py3-none-any.whl:
Publisher:
publish.yml on mtillman14/scistack
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scistackplot-0.1.26-py3-none-any.whl -
Subject digest:
6158dec7614e3e6fb861d2cb2acd4f46cd8128bf63907e59ae938096550dc4a5 - Sigstore transparency entry: 2818134257
- Sigstore integration time:
-
Permalink:
mtillman14/scistack@dceb1ef3ad83a0e46bca88afe94a2281e4e6dde6 -
Branch / Tag:
refs/tags/v0.1.26 - Owner: https://github.com/mtillman14
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dceb1ef3ad83a0e46bca88afe94a2281e4e6dde6 -
Trigger Event:
push
-
Statement type: