Plotting#

Publication-quality plotting: forest plots, interaction plots, volcanoes, UMAPs, GSEA heatmaps.

sctrial.plotting.did_volcano_frame(df: DataFrame, *, effect_col: str = 'beta_DiD', p_col: str = 'p_DiD', out_col: str = 'neglog10p', p_floor: float = 1e-300) DataFrame[source]#

Return a copy with an added -log10(p) column for volcano plots.

Parameters:
  • df – Input results DataFrame.

  • effect_col – Column name for effect sizes.

  • p_col – Column name for p-values.

  • out_col – Name of the output column to add.

  • p_floor – Minimum p-value used for log transform.

Returns:

Copy of df with an added out_col column.

Return type:

pd.DataFrame

sctrial.plotting.plot_abundance_interaction(adata: AnnData, celltype: str, design: TrialDesign, visits: tuple[str, str] | None = None, ax: Axes | None = None) Axes[source]#

Plot cell type abundance (proportion) by arm and visit.

Parameters:
  • adata – AnnData object.

  • celltype – Cell type to plot.

  • design – TrialDesign object (must have celltype_col).

  • visits – Tuple of (baseline, followup) visit labels.

  • ax – Optional matplotlib axes.

Returns:

The axes containing the abundance plot.

Return type:

matplotlib.axes.Axes

sctrial.plotting.plot_did_forest(df: pd.DataFrame, *, feature_col: str = 'feature', beta_col: str = 'beta_DiD', se_col: str = 'se_DiD', p_col: str = 'p_DiD', alpha: float = 0.05, title: str = 'DiD Effect Sizes', ax: Axes | None = None) Axes[source]#

Plot a forest plot of DiD effect sizes with confidence intervals.

Parameters:
  • df – DataFrame returned by did_table or abundance_did.

  • feature_col – Column name for features/cell types.

  • beta_col – Column name for effect sizes.

  • se_col – Column name for standard errors.

  • p_col – Column name for p-values (to indicate significance).

  • alpha – Significance threshold for highlighting.

  • title – Plot title.

  • ax – Optional matplotlib axes.

Returns:

The axes containing the forest plot.

Return type:

matplotlib.axes.Axes

sctrial.plotting.plot_did_forest_interactive(df: DataFrame, *, feature_col: str = 'feature', beta_col: str = 'beta_DiD', se_col: str = 'se_DiD', p_col: str = 'p_DiD', alpha: float = 0.05, title: str = 'DiD Effect Sizes') Any[source]#

Interactive forest plot using Plotly.

Parameters:
  • df – DataFrame with DiD results (from did_table or abundance_did).

  • feature_col – Column name for feature labels (y-axis).

  • beta_col – Column name for effect size estimates.

  • se_col – Column name for standard errors (used for 95 % CI error bars).

  • p_col – Column name for p-values (used to color significant points).

  • alpha – Significance threshold for coloring points.

  • title – Plot title.

Returns:

Interactive forest plot.

Return type:

plotly.graph_objects.Figure

sctrial.plotting.plot_did_volcano_interactive(df: DataFrame, *, beta_col: str = 'beta_DiD', p_col: str = 'p_DiD', title: str = 'DiD Volcano Plot') Any[source]#

Interactive volcano plot using Plotly.

Parameters:
  • df – DataFrame with DiD results.

  • beta_col – Column name for effect size estimates (x-axis).

  • p_col – Column name for p-values (y-axis as -log10(p)).

  • title – Plot title.

Returns:

Interactive volcano plot.

Return type:

plotly.graph_objects.Figure

sctrial.plotting.plot_gsea_heatmap(gsea_results: Any, collection: str | None = None, fdr_thresh: float = 0.25, top_n: int = 30, pool_col: str = 'pool', term_col: str = 'Term', nes_col: str = 'NES', fdr_col: str = 'FDR q-val', figsize: tuple[float, float] = (12, 10), title: str | None = None) Axes[source]#

Heatmap of GSEA NES across pools (cell types).

Parameters:
  • gsea_results – Merged GSEA results table.

  • collection – If provided, subset to this collection (e.g. ‘HALLMARK’).

  • fdr_thresh – Only include pathways that are significant (FDR < thresh) in at least one pool.

  • top_n – Number of top pathways to show (ranked by minimum FDR across pools).

  • figsize – Figure size.

  • title – Optional title.

Returns:

The axes containing the heatmap.

Return type:

matplotlib.axes.Axes

sctrial.plotting.plot_gsea_radar(gsea_results: pd.DataFrame, term: str, pool_col: str = 'pool', nes_col: str = 'NES', term_col: str = 'Term', fdr_col: str = 'FDR q-val', title: str | None = None, figsize: tuple[float, float] = (6, 6)) Figure[source]#

Radar (spider) plot of GSEA NES across pools/cell types.

Parameters:
  • gsea_results – Merged GSEA results table.

  • term – The pathway term to plot.

  • pool_col – Column identifying cell types or pools.

  • nes_col – Column with NES values.

  • term_col – Column containing pathway term names.

  • fdr_col – Column containing FDR q-values (used for disambiguation).

  • title – Plot title.

  • figsize – Figure size.

Returns:

The figure containing the radar plot.

Return type:

matplotlib.figure.Figure

sctrial.plotting.plot_module_umap_panel(adata: AnnData, module_cols: Sequence[str], celltype_col: str = 'celltype', umap_key: str = 'X_umap', n_cols: int = 2, cmap: str = 'magma', figsize: tuple[float, float] = (12, 10), point_size: float = 6, alpha: float = 0.7, label_fontsize: int = 8) Figure[source]#

Plot cell-type UMAP plus module score UMAP panels.

Creates a multi-panel figure with one cell-type reference UMAP and one UMAP per module score column, all sharing the same embedding coordinates.

Parameters:
  • adata – AnnData object with a UMAP embedding in obsm[umap_key].

  • module_cols – Column names in adata.obs containing module scores to plot.

  • celltype_col – Column in adata.obs with cell-type labels (used in reference panel).

  • umap_key – Key in adata.obsm for UMAP coordinates.

  • n_cols – Number of columns in the subplot grid.

  • cmap – Matplotlib colormap for module score panels.

  • figsize – Figure size (width, height).

  • point_size – Scatter point size.

  • alpha – Point transparency.

  • label_fontsize – Font size for cell-type labels on the reference panel.

Returns:

The figure containing the UMAP panel.

Return type:

matplotlib.figure.Figure

Plot pre-treatment trends by arm to visually assess parallel trends.

Produces a point-plot of mean feature values across visits, separately for each arm, to help evaluate the parallel-trends assumption.

Parameters:
  • adata – AnnData object.

  • feature – Feature to plot (gene name in var_names or column in obs).

  • design – TrialDesign object specifying arm and visit columns.

  • visits – Sequence of visit labels to include (should be pre-treatment visits).

  • layer – Layer for gene expression (None uses adata.X).

  • ax – Optional matplotlib axes; a new figure is created if None.

Returns:

Axes containing the parallel trends plot.

Return type:

matplotlib.axes.Axes

sctrial.plotting.plot_trial_dotplot(adata: AnnData, features: Sequence[str], design: TrialDesign, visits: tuple[str, str] | None = None, use_raw: bool | None = None, standard_scale: str | None = None, cmap: str = 'Reds', **kwargs) Any[source]#

Dotplot of features across cell types and trial arms.

Replicates the ‘celltype_treatment’ dotplot pattern.

Parameters:
  • adata – AnnData object.

  • features – List of gene names to include.

  • design – TrialDesign object (must have celltype_col).

  • visits – Optional (baseline, followup) visit tuple to subset.

  • use_raw – Whether to use adata.raw. Defaults to True if raw exists.

  • standard_scale – Scanpy standard_scale parameter ("var" or "group").

  • cmap – Colormap name.

  • **kwargs – Additional arguments passed to scanpy.pl.dotplot.

Returns:

The Scanpy dotplot object (allows further customization).

Return type:

scanpy.pl.DotPlot

sctrial.plotting.plot_trial_interaction(adata: AnnData, feature: str, design: TrialDesign, visits: tuple[str, str] | None = None, layer: str | None = None, color_palette: dict | None = None, ax: Axes | None = None) Axes[source]#

Plot mean expression (interaction plot) by arm and visit.

This visualizes the DiD effect: the change from baseline to follow-up across treatment arms.

Parameters:
  • adata – AnnData object.

  • feature – Gene name or obs column to plot.

  • design – TrialDesign object.

  • visits – Tuple of (baseline, followup) visit labels.

  • layer – Layer for gene expression.

  • color_palette – Optional colour mapping for arms.

  • ax – Optional matplotlib axes.

Returns:

The axes containing the interaction plot.

Return type:

matplotlib.axes.Axes

sctrial.plotting.plot_trial_umap(adata: AnnData, feature: str, design: TrialDesign, visits: tuple[str, str] | None = None, layer: str | None = None, cmap: str = 'magma', figsize: tuple[float, float] = (12, 8)) Figure[source]#

Create a panel of UMAPs stratified by arm and visit.

This creates a 2x2 panel (Treated/Control x Baseline/Followup) showing the expression of a feature on the UMAP embedding.

Parameters:
  • adata – AnnData object with ‘X_umap’ in obsm.

  • feature – Gene or module score.

  • design – A TrialDesign object.

  • visits – Tuple of (baseline, followup) visit labels.

  • layer – Expression layer.

  • cmap – Colormap.

  • figsize – Figure size.

Returns:

fig

Return type:

matplotlib.figure.Figure

sctrial.plotting.plot_trial_umap_panel(adata: AnnData, feature: str, design: TrialDesign, visits: tuple[str, str] | None = None, layer: str | None = None, cmap: str = 'magma', figsize: tuple[float, float] = (16, 8), title: str | None = None) Figure[source]#

Combined UMAP panel: Cell Types + 4 Trial-stratified UMAPs.

Produces a 1×3 grid: a large cell-type reference UMAP on the left and a 2×2 grid of feature UMAPs (Treated/Control × Baseline/Followup) on the right.

Parameters:
  • adata – AnnData object with X_umap in obsm.

  • feature – Gene name or obs column to display.

  • design – TrialDesign object (must have celltype_col set).

  • visits – Tuple of (baseline, followup) visit labels; uses design.primary_visits() if None.

  • layer – Expression layer for gene features (None uses adata.X).

  • cmap – Matplotlib colormap for the feature panels.

  • figsize – Figure size (width, height).

  • title – Optional suptitle; defaults to "Trial UMAP Panel: {feature}".

Returns:

The figure containing the UMAP panel.

Return type:

matplotlib.figure.Figure

sctrial.plotting.plot_within_arm_comparison(adata: AnnData, arm: str, feature: str, design: TrialDesign, visits: tuple[str, str], layer: str | None = None, plot_type: Literal['box', 'paired'] = 'paired', ax: Axes | None = None) Axes[source]#

Plot within-arm longitudinal change.

Parameters:
  • adata – AnnData object.

  • arm – The arm to plot (e.g., design.arm_treated).

  • feature – Gene name or module score.

  • design – A TrialDesign object.

  • visits – Tuple of (pre, post) visit labels.

  • layer – Expression layer.

  • plot_type

    • ‘box’: standard boxplot with points.

    • ’paired’: lines connecting pre/post values for each participant.

  • ax – Optional matplotlib axes.

Returns:

The axes containing the within-arm comparison plot.

Return type:

matplotlib.axes.Axes

sctrial.plotting.signed_logp(df: DataFrame, *, effect_col: str = 'beta_DiD', p_col: str = 'p_DiD', p_floor: float = 1e-300) Series[source]#

Return sign(effect) * -log10(p) as a Series aligned to df.index.

Parameters:
  • df – Input results DataFrame.

  • effect_col – Column name for effect sizes.

  • p_col – Column name for p-values.

  • p_floor – Minimum p-value used for log transform.

Returns:

Signed -log10(p) values aligned to df.index.

Return type:

pd.Series