File size: 2,714 Bytes
925ee3b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | """Phase portrait plotting (unspliced vs spliced colored by gamma)."""
from __future__ import annotations
from typing import Sequence
import matplotlib.pyplot as plt
import numpy as np
from anndata import AnnData
from .._constants import SMOOTHED_UNSPLICED, SMOOTHED_SPLICED, GAMMA
from .._utils import get_layer, require_layers
from ._utils import setup_axes, save_or_show
def phase_portrait(
adata: AnnData,
genes: str | Sequence[str],
color_by: str = GAMMA,
ncols: int = 3,
figsize_per: tuple[float, float] = (4, 3.5),
cmap: str = "viridis",
save: str | None = None,
show: bool = True,
ax: plt.Axes | None = None,
) -> plt.Figure | None:
"""Plot phase portrait (unspliced vs spliced) colored by gamma.
Parameters
----------
adata
Annotated data matrix.
genes
Gene name(s) to plot.
color_by
Layer to use for coloring. Default ``'gamma'``.
ncols
Number of columns in multi-gene grid.
figsize_per
Size per subplot panel.
cmap
Colormap name.
save
Path to save figure.
show
Whether to display the figure.
ax
Pre-existing axes (only for single gene).
"""
require_layers(adata, SMOOTHED_UNSPLICED, SMOOTHED_SPLICED)
if isinstance(genes, str):
genes = [genes]
u = get_layer(adata, SMOOTHED_UNSPLICED)
s = get_layer(adata, SMOOTHED_SPLICED)
if color_by in adata.layers:
colors = get_layer(adata, color_by)
else:
colors = None
n_genes = len(genes)
if n_genes == 1 and ax is not None:
fig, ax = setup_axes(ax)
axes_list = [ax]
else:
nrows = (n_genes + ncols - 1) // ncols
fig, axes = plt.subplots(
nrows, ncols,
figsize=(figsize_per[0] * ncols, figsize_per[1] * nrows),
squeeze=False,
)
axes_list = axes.ravel().tolist()
gene_names = adata.var_names.tolist()
for i, gene in enumerate(genes):
if gene not in gene_names:
continue
gi = gene_names.index(gene)
ax_i = axes_list[i]
c = colors[:, gi] if colors is not None else None
sc = ax_i.scatter(
s[:, gi], u[:, gi],
c=c, cmap=cmap, s=3, alpha=0.6, rasterized=True,
)
ax_i.set_xlabel("Spliced (Ms)")
ax_i.set_ylabel("Unspliced (Mu)")
ax_i.set_title(gene)
if c is not None:
plt.colorbar(sc, ax=ax_i, label=color_by)
# Hide unused axes
for j in range(n_genes, len(axes_list)):
axes_list[j].set_visible(False)
fig.tight_layout()
save_or_show(fig, save, show)
return fig if not show else None
|