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.main()[source]#

Generate figures from the analysis artefacts.

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 to docs/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 package rcParams in 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.Sequence of str, 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>.json sidecar, alongside the package version and the time of writing.

Returns:

The written image paths, in formats order.

Return type:

list of pathlib.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. The figures publish command 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:

pathlib.Path

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:

pathlib.Path

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 align run’s reproduction inputs.

Parameters:
  • run_directory (pathlib.Path) – A completed align run directory.

  • root (pathlib.Path) – The monorepo root, used to resolve the upstream fit run 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:

tuple

figures.data.load_selection_summary(run_directory)[source]#

Load the per-component selection summary from a select run directory.

Parameters:

run_directory (pathlib.Path) – A completed select run directory.

Returns:

The summary table, one row per number of components, sorted by component count.

Return type:

pandas.DataFrame

figures.data.load_replication(run_directory)[source]#

Load a replicate run’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:

tuple

figures.data.load_stability(run_directory)[source]#

Load a stability run’s per-fit comparisons, aggregate, and mean overlap.

Returns:

(comparisons, aggregate, overlap_mean): one row per compared fit, the aggregate dictionary (aggregate.json), and the mean class-overlap matrix.

Return type:

tuple

figures.data.load_nmin(run_directory)[source]#

Load an nmin run’s per-fit metrics, per-size summary, and floor metrics.

Returns:

(per_fit, summary, metrics): one row per (size, replicate) fit, the per-size summary, and the manifest metrics (the floor and its bootstrap interval).

Return type:

tuple

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 align run.

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, with mapping (class id to named class), correlations (class id to a per-class profile correlation or None), overall_correlation, and anchors_hold.

  • our_proportions (dict of int to float) – The recovered class proportions, by class id.

  • published_proportions (dict of str to float) – The published class proportions, by named class.

  • comparison (dict, optional) – A second condition’s reproduction (the V9 subset), with keys signature, alignment, and proportions mirroring the primary arguments. When given, each panel adds the subset’s recovered signature and the size line reads full / 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:

matplotlib.figure.Figure

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 select summary table.

Parameters:
  • summary (pandas.DataFrame) – The per-component summary from analysis.selection, with an n_components column and <name>_mean / <name>_std columns for each criterion drawn.

  • reference_k (int, default 4) – The number of classes to mark with a reference line (the Litman choice).

  • criteria (collections.abc.Sequence of str, optional) – The information criteria to draw in the first panel; the first is emphasised. Defaults to ("bic", "aic", "caic"). Ignored when comparison is 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:

matplotlib.figure.Figure

Raises:

ValueError – When summary is 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 stability run.

Parameters:
  • comparisons (pandas.DataFrame) – One row per compared fit, with overall_correlation and adjusted_rand_index.

  • aggregate (dict) – The aggregate metrics, with category_correlation_mean (one entry per category) and a run descriptor (n_fits/top_k or n_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:

matplotlib.figure.Figure

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 nmin run.

Parameters:
  • per_fit (pandas.DataFrame) – One row per (size, replicate) fit, with size, overall_correlation, and smallest_class_proportion.

  • summary (pandas.DataFrame) – The per-size summary, with the same three columns.

  • metrics (dict) – The floor metrics: floor and floor_ci90 (a two-element list, or None), and the benchmark correlation.

Returns:

A two-panel figure: recovery against size, and the smallest class proportion.

Return type:

matplotlib.figure.Figure

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 replicate run.

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), with overall_correlation, category_correlation (one entry per category), and optionally n_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:

matplotlib.figure.Figure

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.

class figures.publish.FigureSpec(name, source_stage, file_name)[source]#

One publishable figure.

name#

The figure’s key: its figures <name> build command and its documentation handle.

Type:

str

source_stage#

The analysis stage whose cached run the figure visualises.

Type:

str

file_name#

The figure’s base file name, without a suffix.

Type:

str

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 run figures.data.resolve_run() would pick.

Returns:

The written PNG in the documentation tree.

Return type:

pathlib.Path

Raises:

FileNotFoundError – When no PNG has been rendered for the figure yet, so the caller is told to build it first.