# Load spatial mouse data
import scanpy as sc
# Load the actual spatial mouse data
spatial_mouse_data = sc.read_h5ad('/data/analysis/data_mcandrew/00_allos_0.6_TAB/data/mouse_cbs/mouse_sit/two_mouse_cbs.h5ad')
# Rename spatial coordinates to X_spatial for consistency
if "spatial" in spatial_mouse_data.obsm:
spatial_mouse_data.obsm["X_spatial"] = spatial_mouse_data.obsm["spatial"]
print(spatial_mouse_data)
print(f"Spatial coordinates shape: {spatial_mouse_data.obsm['X_spatial'].shape}")Composed Plots
LegendPanelBuilder
def LegendPanelBuilder(
ax:Optional[plt.Axes]
):
Builder for creating consistent legend panels across different composed plots.
Automatically stacks legend elements vertically with proper spacing: - Categorical legends (group colors) - Colorbars (PSI, GEX, etc.) - Dot size legends (prevalence)
DotSizeSlot
def DotSizeSlot(
sizes:List[float]=None, labels:List[str]=None, title:str='Prevalence\n(dot size)'
)->None:
Slot for dot size legend.
ColorbarSlot
def ColorbarSlot(
norm:mpl.colors.Normalize, cmap:mpl.colors.Colormap, label:str=''
)->None:
Slot for continuous colorbar.
CategoricalSlot
def CategoricalSlot(
groups:List[str], color_map:Dict[str, str], title:str='Groups'
)->None:
Slot for categorical legend (group colors).
make_aligned_transcript_panel_layout
def make_aligned_transcript_panel_layout(
tp:TranscriptPlots, transcripts_ids:List[str], n_panel_cols:int, fig_width:float=None, draw_cds:bool=True,
show_ruler:bool=True, bands_frac_top:float=0.0, bands_frac_bottom:float=0.0
)->PanelLayout:
Create a transcript panel layout with PERFECT alignment.
This wrapper around make_transcript_panel_layout fixes: 1. Panel bounds so dots/cells align exactly with transcript intron lines 2. Band positions (top/bottom) to attach to the realigned panel 3. Legend panel height to match the actual content height
Examples
Composed plots combining transcript structures with quantitative visualizations
API reference
plot_isoform_heatmap_composed
def plot_isoform_heatmap_composed(
transcript_data, # Transcript annotation data
adata, # Annotated data object with transcript counts
gene_id:str, # Gene ID to plot
group_col:str, # Column in adata.obs defining groups (e.g., 'cell_type')
top_n:int=2, # Number of top isoforms to show
estimator:str='pseudobulk', # PSI estimator
dirichlet_alpha:float=0.5, # Dirichlet alpha parameter
epsilon:float=1e-06, # Small value to avoid division by zero
visible_groups:Optional[List[str]]=None, # Subset of groups to display
cmap:str='magma', # Colormap for PSI heatmap
colorbar_label:str='PSI', # Label for PSI colorbar
fig_width:float=20.0, # Figure width in inches
draw_cds:bool=True, # Whether to draw CDS regions
show_ticks:bool=True, # Whether to show ruler ticks
add_gex_band:bool=False, # Whether to add gene expression band
add_group_color_band:bool=False, # Whether to add group color band
group_color_map:Optional[Dict[str, str]]=None, # Custom color map for groups
gex_band_position:str='top', # Position of GEX band ("top" or "bottom")
group_band_position:str='bottom', # Position of group color band ("top" or "bottom")
show_panel_colorbar:bool=False, # default off: use legend instead
show_group_legend:bool=False, # default off: group labels on x-axis are sufficient
legend_pad:float=0.02, # horizontal padding between plot and legend
label_offset_h:float=0, # horizontal offset for x-axis labels (positive = right)
label_offset_v:float=0, # vertical offset for x-axis labels (positive = down)
row_pitch:float=0.45, # vertical spacing between transcript rows (smaller = tighter)
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
)->Tuple[plt.Figure, List[str], List[str], np.ndarray]: # The matplotlib figure
Plot composed figure with transcript structures and heatmap.
plot_isoform_dot_composed
def plot_isoform_dot_composed(
transcript_data, adata, gene_id:str, group_col:str, top_n:int=2, estimator:str='pseudobulk',
dirichlet_alpha:float=0.5, epsilon:float=1e-06, visible_groups:Optional[List[str]]=None,
size_mode:str='prevalence', psi_threshold:float=0.05, cmap:str='magma', colorbar_label:str='PSI',
fig_width:float=20.0, draw_cds:bool=True, show_ticks:bool=True, add_gex_band:bool=False,
add_group_color_band:bool=False, group_color_map:Optional[Dict[str, str]]=None, gex_band_position:str='top',
group_band_position:str='bottom', show_panel_colorbar:bool=False, # use legend instead
label_offset_h:float=0.0, # horizontal offset for x-axis labels (positive = right)
label_offset_v:float=0.0, # vertical offset for x-axis labels (positive = down)
row_pitch:float=0.45, # vertical spacing between transcript rows (smaller = tighter)
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
)->Tuple[plt.Figure, List[str], List[str], np.ndarray, np.ndarray]:
Call self as a function.
plot_isoform_violin_composed
def plot_isoform_violin_composed(
transcript_data, # TranscriptData object for gene/transcript lookups
adata, # Annotated data object with transcript counts
gene_id:str, # Gene ID to plot
group_col:str, # Column in adata.obs defining groups (e.g., 'cell_type')
gene_col:str='geneId', # Column in adata.var mapping transcripts to genes
layer:str | None=None, # Layer in adata.layers to use. If None, uses adata.X
top_n:int | None=None, # Number of top isoforms to plot by mean expression.
Mutually exclusive with `transcripts`.
transcripts:List[str] | None=None, # Specific transcript IDs to plot.
Mutually exclusive with `top_n`.
log1p:bool=True, # Apply log1p transformation to counts
drop_zeros:bool=False, # Remove zero values before plotting
min_cells_per_group:int=10, # Minimum cells required per group to include
fig_width:float=20.0, # Overall figure width in inches
draw_cds:bool=True, # Draw CDS regions on transcript structures
show_ticks:bool=True, # Show genomic coordinate ruler
palette:str | list='tab10', # Color palette for groups (used if group_color_map is not provided)
stripplot:bool=True, # Overlay scatter points on violins
point_size:float=2.0, # Size of scatter points
point_alpha:float=0.4, # Alpha transparency of points
jitter:float=0.25, # Horizontal jitter width for points
sharey:bool=False, # Share y-axis across all violin panels (default False for better visibility)
visible_groups:Optional[List[str]]=None, # Subset of groups to display. If None, all groups are shown.
add_gex_band:bool=False, # Add a gene-expression (CP10k) quantitative band above the panel.
add_group_color_band:bool=False, # Add colored band showing group categories
group_color_map:Optional[Dict[str, str]]=None, # Custom color mapping for groups. If provided, overrides palette for
both violin colors and group color band.
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
panel_x0:float=1.15, # horizontal gap between transcripts and violin panel
)->Tuple[plt.Figure, List[str], List[str]]: # The matplotlib figure
Plot violin plots showing isoform expression with transcript structures.
Creates a multi-panel layout with transcript structures on the left and violin plots for each isoform-group combination on the right.
plot_isoform_replicates_composed
def plot_isoform_replicates_composed(
transcript_data, # Transcript data object for structure plots
adata, # Annotated data object
gene_id:str, # Gene ID to plot
group_col:str, # Column in adata.obs defining groups (e.g., 'cell_type')
replicate_col:str, # Column in adata.obs defining replicates (e.g., 'batch', 'sample_id')
top_n:int=2, # Number of top isoforms to plot
estimator:str='pseudobulk', # PSI estimator ('pseudobulk', 'dirichlet', 'cell-mean', 'cell-median', 'coverage-weighted')
dirichlet_alpha:float=0.5, # Dirichlet alpha parameter
epsilon:float=1e-06, # Small value to avoid division by zero
visible_groups:Optional[List[str]]=None, # Subset of groups to display
fig_width:float=20.0, # Figure width in inches
draw_cds:bool=True, # If True, draw CDS regions in transcript structures
show_ticks:bool=True, # If True, show ruler ticks
add_gex_band:bool=False, # If True, add GEX band
add_group_color_band:bool=False, # If True, add group color band
group_color_map:Optional[Dict[str, str]]=None, # Custom color map for groups
box_overlay:bool=True, # If True, overlay boxplots on scatter points
point_size:float=4.0, # Size of scatter points
point_alpha:float=0.85, # Alpha transparency of points
jitter_width:float=0.12, # Width of horizontal jitter for points
label_wrap:int=14, # Width for wrapping x-axis labels
label_rot:int=35, # Rotation angle for x-axis labels
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
)->Tuple[plt.Figure, List[str], List[str], Dict[Tuple[int, int], np.ndarray]]: # The matplotlib figure
Composed plot: transcript structures + replicate PSI variability.
Left: Transcript structure glyphs Right: Replicate plots showing PSI variability across biological replicates
plot_isoform_stacked_bar_composed
def plot_isoform_stacked_bar_composed(
transcript_data, # Transcript annotation data
adata, # Annotated data object with transcript counts
gene_id:str, # Gene ID to plot
group_col:str, # Column in adata.obs defining groups (e.g., 'cell_type')
top_n:Optional[int]=None, # Number of top isoforms to show separately. Others grouped as "Other".
If None, shows all isoforms.
estimator:str='pseudobulk', # PSI estimator ('pseudobulk', 'dirichlet', 'cell-mean', 'cell-median', 'coverage-weighted')
dirichlet_alpha:float=0.5, # Dirichlet alpha parameter
epsilon:float=1e-06, # Small value to avoid division by zero
compute_on_selection_only:bool=False, # If True, compute PSI only on selected top_n isoforms (rescaled to sum to 100%).
If False, compute PSI on all isoforms and show remaining as "Other" category.
visible_groups:Optional[List[str]]=None, # Subset of groups to display. If None, all groups are shown.
fig_width:float=16.0, # Figure width in inches
draw_cds:bool=True, # Whether to draw CDS regions in transcript structures
show_ticks:bool=True, # Whether to show ruler ticks
label_wrap:int=14, # Width for wrapping x-axis labels
label_rot:int=45, # Rotation angle for x-axis labels
show_values:bool=False, # Whether to show percentage values on bars
show_title:bool=False, # Whether to show the figure title
add_group_color_band:bool=False, # Add a categorical color band above the panel showing group identity.
group_color_map:Optional[Dict[str, str]]=None, # Custom color mapping for groups used in the color band.
add_gex_band:bool=False, # Add a gene-expression (CP10k) quantitative band above the panel.
add_gex_bar:bool=False, # Whether to add gene expression bar above stacked bars
gex_bar_height:float=0.003, # Fixed height of gene expression bar as fraction of main plot height
gex_legend_width:float=0.35, # Width of the GEX legend colorbar (as fraction, 0-1)
gex_legend_x:float=0.15, # Horizontal position of GEX legend colorbar (0=left, 1=right)
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
)->Tuple[plt.Figure, List[str], List[str], np.ndarray]: # The matplotlib figure
Plot composed figure with transcript structures and stacked bar chart.
Creates a two-panel figure showing: - Left: Transcript structures for isoforms - Right: Stacked bar chart showing isoform composition per group
Colors are matched between transcript structures and bar segments.
plot_isoform_umap_composed
def plot_isoform_umap_composed(
transcript_data, adata, gene_id:str, group_col:str, top_n:int=2, estimator:str='pseudobulk',
dirichlet_alpha:float=0.5, epsilon:float=1e-06, visible_groups:Optional[List[str]]=None,
show_individual_colorbars:bool=False, # If True, show a small colorbar for each UMAP plot panel.
use_per_panel_scale:bool=False, # If True, each panel has its own colorbar scale based on its data.
If False (default), all panels share a global scale.
fig_width:float=20.0, draw_cds:bool=True, show_ticks:bool=True, add_gex_band:bool=False,
add_group_color_band:bool=False, group_color_map:Optional[Dict[str, str]]=None, umap_basis:str='umap',
umap_cmaps:Optional[List[str]]=None, umap_max_cols:int=2, umap_size:float=5.0, umap_alpha:float=0.9,
use_global_vmin_vmax:bool=True, vmin:Optional[float]=None, vmax:Optional[float]=None,
use_density:bool=False, # If True, show KDE-based density instead of raw expression.
density_adjust:float=1.0, # Bandwidth adjustment for KDE (only used if use_density=True).
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
)->Tuple[plt.Figure, List[str], List[str]]:
Composed plot: transcript structures + UMAP embeddings.
Left: Transcript structure glyphs Right: Tiled UMAP plots (one per isoform)
plot_isoform_density_composed
def plot_isoform_density_composed(
transcript_data, adata, gene_id:str, group_col:str, top_n:int=2, estimator:str='pseudobulk',
dirichlet_alpha:float=0.5, epsilon:float=1e-06, visible_groups:Optional[List[str]]=None,
show_individual_colorbars:bool=False, # If True, show a small colorbar for each density plot panel.
use_per_panel_scale:bool=False, # If True, each panel has its own colorbar scale based on its data.
If False (default), all panels share a global scale.
fig_width:float=20.0, draw_cds:bool=True, show_ticks:bool=True, add_gex_band:bool=False,
add_group_color_band:bool=False, group_color_map:Optional[Dict[str, str]]=None, density_basis:str='umap',
density_cmaps:Optional[List[str]]=None, density_max_cols:int=2, density_size:float=5.0, density_alpha:float=0.9,
density_adjust:float=1.0, use_global_vmin_vmax:bool=True, vmin:Optional[float]=None, vmax:Optional[float]=None,
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
)->Tuple[plt.Figure, List[str], List[str]]:
Composed plot: transcript structures + density (KDE) embeddings.
Left: Transcript structure glyphs Right: Tiled density plots (one per isoform, showing spatial density via KDE)
plot_isoform_spatial_composed
def plot_isoform_spatial_composed(
transcript_data, adata, gene_id:str, group_col:str, top_n:int=2, estimator:str='pseudobulk',
dirichlet_alpha:float=0.5, epsilon:float=1e-06, visible_groups:Optional[List[str]]=None,
show_individual_colorbars:bool=True, use_per_panel_scale:bool=False, fig_width:float=20.0, draw_cds:bool=True,
show_ticks:bool=True, add_gex_band:bool=False, add_group_color_band:bool=False,
group_color_map:Optional[Dict[str, str]]=None, spatial_basis:str='spatial', spatial_cmap:Optional[str]=None,
spatial_cmaps:Optional[List[str]]=None, spatial_max_cols:int=2, spatial_size:float=5.0, spatial_alpha:float=0.9,
use_global_vmin_vmax:bool=True, vmin:Optional[float]=None, vmax:Optional[float]=None, invert_y:bool=True,
use_density:bool=False, density_adjust:float=1.0, aspect_equal:bool=True, color_offset:int=0,
intron_scale:float=0.15, # intron compression (smaller = more compressed)
)->Tuple[plt.Figure, List[str], List[str]]:
Composed plot: transcript structures + spatial embeddings.
Left: Transcript structure glyphs Right: Tiled spatial plots (one per isoform)
If use_density=False (default): colour = raw isoform expression. If use_density=True: colour = KDE-based spatial density of that isoform.
spatial_cmap: single colormap name applied to all panels (e.g. “Reds”, “magma”). Overrides the per-mode default. spatial_cmaps takes precedence if also provided. spatial_cmaps: per-isoform colormap list; overrides spatial_cmap. aspect_equal: if True (default), each spatial subplot uses equal x/y scaling, preserving true tissue geometry. Set False to fill the available cell area. use_per_panel_scale: if True, each panel has its own colorbar scale based on its data. If False (default), all panels share a global scale. color_offset: rotate transcript color palette by this many steps.
make_group_color_map
def make_group_color_map(
groups:List[str], cmap_name:str='tab20'
)->Dict[str, str]:
Create a color map for categorical groups.
plot_isoform_spatial_composed_HD
def plot_isoform_spatial_composed_HD(
transcript_data, adata, gene_id:str,
top_n:int=2, # Number of top-expressed isoforms to show (by total expression).
fig_width:float=20.0, draw_cds:bool=True, show_ticks:bool=True, show_individual_colorbars:bool=True,
spatial_cmap:Optional[str]=None, # Single colormap applied to all panels (e.g. "Reds", "magma").
spatial_cmaps takes precedence if also provided.
spatial_cmaps:Optional[List[str]]=None, # Per-isoform colormap list; overrides spatial_cmap.
spatial_max_cols:int=2, spatial_size:float=5.0, spatial_alpha:float=0.9, invert_y:bool=True,
aspect_equal:bool=True, # If True (default), each spatial subplot uses equal x/y scaling,
preserving true tissue geometry.
color_offset:int=0, # Rotate transcript color palette by this many steps.
row_pitch:float=0.45, intron_scale:float=0.15, # intron compression (smaller = more compressed)
layer:Optional[str]=None, # Layer to read expression from. Defaults to 'counts' if present.
transcripts:Optional[List[str]]=None, # Explicit transcript IDs — bypasses top_n selection.
log_scale:bool=True, # Use LogNorm colorscale. Default True for visium_like style.
norm_per_spot:bool=False, # Normalise by per-spot library size before plotting.
norm_target:float=10000.0, # CPM target when norm_per_spot=True (default 1e4).
hd_marker:str='s', hd_bg_color:str='#E6E6E6', hd_bg_alpha:float=0.35, hd_bg_size_factor:float=1.0,
bin_factor:Optional[int]=None, rotate:float=0
)->Tuple[plt.Figure, List[str]]:
Composed plot for Visium HD: transcript structure glyphs + spatial scatter panels.
Renders square-bin scatter on a white background (visium_like style), using array_col/array_row from adata.obs for spatial coordinates.
plot_isoform_heatmap_percell_composed
def plot_isoform_heatmap_percell_composed(
transcript_data, # Transcript annotation data
adata, # Annotated data object with transcript counts
gene_id:str, # Gene ID to plot
group_col:str, # Column in adata.obs for grouping/sorting cells (e.g., 'cell_type')
top_n:int=2, # Number of top isoforms to include
epsilon:float=1e-06, # Small value to avoid division by zero
cell_subset:Optional[List[str]]=None, # Specific cell IDs to include
max_cells:Optional[int]=500, # Maximum number of cells to plot
cluster_within_groups:bool=True, # Whether to hierarchically cluster cells within each group
cmap:str='magma', # Colormap name
colorbar_label:str='PSI', # Label for colorbar
fig_width:float=20.0, # Figure width in inches
draw_cds:bool=True, # Whether to draw CDS regions
show_ticks:bool=True, # Whether to show ruler ticks
add_group_color_band:bool=False, # Add group color band
group_color_map:Optional[Dict[str, str]]=None, # Custom color map for groups
group_band_position:str='bottom', # Position of group color band ("top" or "bottom")
show_panel_colorbar:bool=False, # Whether to show panel colorbar
show_group_boundaries:bool=True, # Whether to show vertical lines between groups
row_pitch:float=0.45, # vertical spacing between transcript rows
intron_scale:float=0.15, # intron compression (smaller = more compressed)
color_offset:int=0, # rotate transcript color palette by this many steps
)->Tuple[plt.Figure, List[str], List[str], np.ndarray]: # The matplotlib figure
Plot a composed per-cell heatmap with transcript structure.
This function combines transcript structure visualization with a per-cell heatmap of isoform PSI values. Cells are sorted by group and optionally clustered within each group.