API reference#
The importable figures API: the command-line interface, the house style and save helper,
the helpers that resolve and load a cached analysis run, the output-path helpers, the
reproduction, model-selection, stability, minimum-stratum-size, and replication figures, and
the helper that publishes rendered figures into the documentation tree.
Command-line interface#
figures command-line interface (Typer).
One subcommand per figure. Each resolves a cached analysis run, builds the figure, and writes
it under artefacts/figures/ with a JSON provenance sidecar.
- figures.cli.reproduce(run=<typer.models.OptionInfo object>, as_of_run=<typer.models.OptionInfo object>, name=<typer.models.OptionInfo object>, fmt=<typer.models.OptionInfo object>)[source]#
Plot the recovered class signatures against the published profile, across conditions.
- figures.cli.select(run=<typer.models.OptionInfo object>, as_of_run=<typer.models.OptionInfo object>, name=<typer.models.OptionInfo object>, fmt=<typer.models.OptionInfo object>)[source]#
Plot the model-selection criteria across the number of latent classes, across conditions.
- figures.cli.replicate(run=<typer.models.OptionInfo object>, as_of_run=<typer.models.OptionInfo object>, name=<typer.models.OptionInfo object>, fmt=<typer.models.OptionInfo object>)[source]#
Plot the SPARK-to-SSC class signatures and the per-category replication across conditions.
- figures.cli.stability(run=<typer.models.OptionInfo object>, name=<typer.models.OptionInfo object>, fmt=<typer.models.OptionInfo object>)[source]#
Plot the profile and membership stability of the reference fit under refitting.
- figures.cli.nmin(run=<typer.models.OptionInfo object>, name=<typer.models.OptionInfo object>, fmt=<typer.models.OptionInfo object>)[source]#
Plot recovery against subsample size and the minimum viable stratum size.
- figures.cli.publish(figure=<typer.models.ArgumentInfo object>, run=<typer.models.OptionInfo object>)[source]#
Copy rendered figures into the committed documentation tree, with provenance.
Each figure is taken from the latest completed run of its source stage (or
--run) and copied todocs/source/_figures/beside a JSON sidecar recording its source. A figure that has not been rendered yet is skipped with a note, so publishing the whole set surfaces what still needs building.
House style and output#
House style for the figures: Matplotlib settings, a palette, and a save helper.
The settings are deliberately small and explicit, so a figure looks the same whoever builds
it. house_style() returns a context manager that applies them around figure
construction without leaking into the global state, and save_figure() writes one file
per format alongside a JSON provenance sidecar.
- figures.style.panel_title(ax, letter, text)[source]#
Set a left-aligned panel title prefixed with a bold letter label.
The letter is rendered in bold and the scientific title follows in the regular weight, so each panel reads as, for example, “A Information criteria”, left-aligned over the axes.
- Parameters:
ax (
matplotlib.axes.Axes) – The axis to title.letter (
str) – The panel letter, shown in bold (for example"A").text (
str) – The scientific title that follows the letter.
- figures.style.house_style()[source]#
Apply the package Matplotlib settings for the duration of the context.
- Yields:
None– Control returns to the caller with the packagercParamsin effect; the previous settings are restored on exit, so the styling does not leak into other figures.
- figures.style.save_figure(fig, stem, *, formats=('pdf', 'png'), provenance=None)[source]#
Write a figure to one file per format and a JSON provenance sidecar.
- Parameters:
fig (
matplotlib.figure.Figure) – The figure to save.stem (
pathlib.Path) – Output path without a suffix; each format appends its own. Parent directories are created if absent.formats (
collections.abc.Sequenceofstr, optional) – File extensions to write; defaults to("pdf", "png"). PDF is the vector format for the manuscript; PNG is the raster preview the docs embed.provenance (
dict, optional) – Extra fields to record in the<stem>.jsonsidecar, alongside the package version and the time of writing.
- Returns:
The written image paths, in
formatsorder.- Return type:
listofpathlib.Path
Output paths for generated figures, under the gitignored artefacts tree.
- figures.paths.figures_dir(root)[source]#
Return the figures output directory,
<root>/artefacts/figures.
- figures.paths.docs_figures_dir(root)[source]#
Return the committed documentation figures directory.
This is
<root>/docs/source/_figures, the one place under version control that holds rendered figures. Thefigures publishcommand copies the chosen PNGs here from the gitignored artefacts tree, and the documentation pages embed them from here.
- figures.paths.figure_stem(root, source_stage, source_hash, name)[source]#
Return the output-path stem for a figure built from one source run.
- Parameters:
root (
pathlib.Path) – The monorepo root.source_stage (
str) – The analysis stage whose run the figure visualises, for example"select".source_hash (
str) – The short hash of that source run, so a figure is traceable to its inputs.name (
str) – The figure’s base name, without a suffix.
- Returns:
<root>/artefacts/figures/<source_stage>/<source_hash>/<name>with no suffix; the save helper appends one suffix per format.- Return type:
Loading analysis runs#
Locating and loading the cached analysis run a figure visualises.
- figures.data.resolve_run(root, stage, run=None)[source]#
Return the run directory to visualise for an analysis stage.
- Parameters:
root (
pathlib.Path) – The monorepo root.stage (
str) – The analysis stage, for example"select".run (
str, optional) – A run’s short hash. When given, that run’s directory is returned. When omitted, the most recently finished run for the stage is chosen (the latest manifest whose status is"ok").
- Returns:
The resolved run directory.
- Return type:
- Raises:
FileNotFoundError – When the named run has no manifest, or when no completed run exists for the stage.
- figures.data.load_alignment(run_directory, root)[source]#
Load an
alignrun’s reproduction inputs.- Parameters:
run_directory (
pathlib.Path) – A completedalignrun directory.root (
pathlib.Path) – The monorepo root, used to resolve the upstreamfitrun for the class proportions.
- Returns:
(our_signature, published_signature, alignment, our_proportions, published_proportions): the recovered class-by-category signature, the published figure-1b signature, the alignment record (alignment.json), the recovered class proportions by class id, and the published proportions by named class.- Return type:
- figures.data.load_selection_summary(run_directory)[source]#
Load the per-component selection summary from a
selectrun directory.- Parameters:
run_directory (
pathlib.Path) – A completedselectrun directory.- Returns:
The summary table, one row per number of components, sorted by component count.
- Return type:
- figures.data.load_replication(run_directory)[source]#
Load a
replicaterun’s metrics and its two category signatures.- Returns:
(metrics, spark_signature, ssc_signature): the metrics dictionary (replication.json) and the two class-by-category signature matrices.- Return type:
Figures#
The reproduction figure: recovered class signatures against the published profile.
Built from an analysis align run, the figure puts each recovered class signature beside
the value read from figure 1b of Litman et al. (2025). One panel per named class shows the
seven-category profile two ways: the recovered signature (solid) and the published target
(dashed). The panels are ordered by published class size, and each title carries the class
proportion (recovered against published) and the per-class profile correlation, or a note
that the class is anchor-confirmed where its published profile is saturated and the
correlation is uninformative.
The figure is the visual form of the reproduction benchmark: a clean match in the developmental-led and saturated classes, and the one real divergence (Social or behavioural showing weaker social-communication and restricted-or-repetitive enrichment than the paper) visible rather than hidden.
- figures.reproduction.reproduction_figure(our_signature, published_signature, alignment, our_proportions, published_proportions, comparison=None)[source]#
Build the reproduction figure from an
alignrun.- Parameters:
our_signature (
pandas.DataFrame) – The recovered class-by-category signature, indexed by class id, one column per category.published_signature (
pandas.DataFrame) – The published figure-1b signature, indexed by named class, with the same columns.alignment (
dict) – The alignment record, withmapping(class id to named class),correlations(class id to a per-class profile correlation orNone),overall_correlation, andanchors_hold.our_proportions (
dictofinttofloat) – The recovered class proportions, by class id.published_proportions (
dictofstrtofloat) – The published class proportions, by named class.comparison (
dict, optional) – A second condition’s reproduction (the V9 subset), with keyssignature,alignment, andproportionsmirroring the primary arguments. When given, each panel adds the subset’s recovered signature and the size line readsfull / V9 vs published.
- Returns:
A two-by-two figure, one panel per named class, each overlaying the recovered and published seven-category profiles.
- Return type:
- Raises:
ValueError – When the two signatures differ in their categories, or the alignment names a class the published signature does not carry.
The model-selection figure: information criteria across the number of classes.
Built from the summary table of an analysis select run, the figure tells the
number-of-classes story in three panels. The information criteria fall and formally minimise
far out along the grid (panel a), the cross-validated log-likelihood elbows at the chosen
four classes (panel b), and higher-class solutions degenerate into tiny, poorly separated
classes (panel c). A reference line marks the four classes chosen by Litman et al.
The naive Lo-Mendell-Rubin proxy that analysis.selection reports is left out, because
that module documents it as not the analytically correct test.
- figures.selection.selection_figure(summary, *, reference_k=4, criteria=('bic', 'aic', 'caic'), comparison=None)[source]#
Build the model-selection figure from a
selectsummary table.- Parameters:
summary (
pandas.DataFrame) – The per-component summary fromanalysis.selection, with ann_componentscolumn and<name>_mean/<name>_stdcolumns for each criterion drawn.reference_k (
int, default4) – The number of classes to mark with a reference line (the Litman choice).criteria (
collections.abc.Sequenceofstr, optional) – The information criteria to draw in the first panel; the first is emphasised. Defaults to("bic", "aic", "caic"). Ignored whencomparisonis given, where the first panel shows the leading criterion alone for both conditions.comparison (
pandas.DataFrame, optional) – A second condition’s summary (the V9 subset). When given, each panel overlays the two conditions, the full release solid and the subset dashed, so the effect of cutting the cohort back to V9 on model selection is visible. The first panel then shows the leading criterion (BIC) for both conditions rather than the three criteria of one.
- Returns:
A three-panel figure: the information criteria, the cross-validated log-likelihood, and the smallest-class proportion.
- Return type:
- Raises:
ValueError – When
summaryis missing a column the figure needs.
The stability figure: how the reference solution holds under refitting.
Built from a stability run (either mode), the figure shows three things. Panel (a)
contrasts the distribution of the seven-category profile correlation, which clusters high,
with the adjusted Rand index, which is more moderate: the class definitions reproduce, while
individual proband assignments are softer at the boundaries. Panel (b) gives the per-category
correlation, uniformly high. Panel (c) is the mean class-overlap matrix, whose diagonal is
each class’s retention.
- figures.stability.stability_figure(comparisons, aggregate, overlap_mean)[source]#
Build the stability figure from a
stabilityrun.- Parameters:
comparisons (
pandas.DataFrame) – One row per compared fit, withoverall_correlationandadjusted_rand_index.aggregate (
dict) – The aggregate metrics, withcategory_correlation_mean(one entry per category) and a run descriptor (n_fits/top_korn_reps/frac).overlap_mean (
pandas.DataFrame) – The mean class-overlap matrix (refit class on rows, reference class on columns).
- Returns:
A three-panel figure: the correlation and Rand-index distributions, the per-category correlation, and the mean overlap matrix.
- Return type:
- Raises:
ValueError – When a required column or metric is missing.
The minimum-viable-stratum-size figure: recovery against sample size.
Built from an nmin run, panel (a) plots the profile correlation of each refit against its
sample size, with the per-size mean, the recovery benchmark, and the isotonic floor and its
bootstrap interval. The floor is drawn as an interval because the recovery metric is noisy
even at ten replicates. Panel (b) shows the smallest class proportion holding well clear of
zero, so the four classes survive at every size.
- figures.nmin.nmin_figure(per_fit, summary, metrics)[source]#
Build the minimum-viable-stratum-size figure from an
nminrun.- Parameters:
per_fit (
pandas.DataFrame) – One row per (size, replicate) fit, withsize,overall_correlation, andsmallest_class_proportion.summary (
pandas.DataFrame) – The per-size summary, with the same three columns.metrics (
dict) – The floor metrics:floorandfloor_ci90(a two-element list, orNone), and thebenchmarkcorrelation.
- Returns:
A two-panel figure: recovery against size, and the smallest class proportion.
- Return type:
- Raises:
ValueError – When a required column is missing.
The cross-cohort replication figure: SPARK class signatures projected onto the SSC.
Built from a replicate run, the figure shows how closely the seven-category class
signatures agree between the SPARK fit and its projection onto the SSC, against the values
Litman et al. (2025) report. Panel (a) scatters every class-by-category value, SSC against
SPARK, around the line of equality; panel (b) gives the per-category correlation with the
published per-category coefficients overlaid. Each per-category coefficient is taken over the
four classes alone, so it shifts easily when one class moves; the overall correlation, over
all 28 class-by-category points, is the stabler quantity. The developmental category sits
below the rest, a gap the replication investigation examines rather than ascribes to a single
cause.
- figures.replication.replication_figure(spark_signature, ssc_signature, metrics, comparison=None)[source]#
Build the cross-cohort replication figure from a
replicaterun.- Parameters:
spark_signature (
pandas.DataFrame) – The class-by-category signature matrices (one row per class, one column per category) for the SPARK fit and its SSC projection. They must share shape and columns.ssc_signature (
pandas.DataFrame) – The class-by-category signature matrices (one row per class, one column per category) for the SPARK fit and its SSC projection. They must share shape and columns.metrics (
dict) – The replication metrics for the primary condition (the full release), withoverall_correlation,category_correlation(one entry per category), and optionallyn_ssc.comparison (
dict, optional) – A second condition’s metrics (the V9-subset projection), with the same keys. When given, the per-category panel groups the two conditions side by side against the published values, so the effect of cutting the training cohort back to V9 is visible.
- Returns:
A two-panel figure: the signature scatter and the per-category correlation.
- Return type:
- Raises:
ValueError – When the two signatures differ in shape or columns, or a metric is missing.
Publishing#
Promoting generated figures into the committed documentation tree.
Figures are rendered under the gitignored artefacts/ directory, so they do not reach the
published documentation on their own. figures publish copies the chosen PNGs into
docs/source/_figures/, a committed directory the documentation pages embed, and writes a
provenance sidecar beside each so a published figure traces back to the analysis run and the
commit it was built from.
Only the rendered PNGs cross into the committed tree. They are aggregate, non-disclosive summaries (class profiles, correlations, drift), so committing them is within the data governance that keeps the rest of the artefacts tree out of the history.
- figures.publish.publish_figure(root, spec, run=None)[source]#
Copy one rendered figure into the documentation tree and record its provenance.
- Parameters:
root (
pathlib.Path) – The monorepo root.spec (
FigureSpec) – The figure to publish.run (
str, optional) – The source run’s short hash. When omitted, the latest completed run of the figure’s source stage is used, the same runfigures.data.resolve_run()would pick.
- Returns:
The written PNG in the documentation tree.
- Return type:
- Raises:
FileNotFoundError – When no PNG has been rendered for the figure yet, so the caller is told to build it first.