AnnData¶
import holoviews as hv
from hv_anndata import A
from hv_anndata.interface import register
register()
hv.extension("bokeh")
Create synthetic data¶
from string import ascii_lowercase
import numpy as np
import pandas as pd
import scipy.sparse as sp
from anndata import AnnData
gen = np.random.default_rng()
x = gen.random((100, 50), dtype=np.float32)
layers = dict(a=sp.random(100, 50, format="csr"))
obs = pd.DataFrame(
dict(type=gen.integers(0, 3, size=100)),
index=pd.Series(range(100)).astype(str).apply(lambda v: "cell-" + v),
)
var_grp = pd.Categorical(
gen.integers(0, 6, size=50), categories=list(ascii_lowercase[:5])
)
var = pd.DataFrame(
dict(grp=var_grp),
index=pd.Series(range(50)).astype(str).apply(lambda v: "gene-" + v),
)
obsm = dict(umap=gen.random((100, 2)))
varp = dict(cons=sp.csr_array(sp.random(50, 50)))
adata = AnnData(x, obs, var, layers=layers, obsm=obsm, varm={}, obsp={}, varp=varp)
/tmp/ipykernel_1993/664159585.py:15: Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.
var_grp = pd.Categorical(
Tabular mode¶
We can select the data to display using the Accessor object A. Here it is important that the data must be indexed along either the obs or the var dimension.
Let us visualize the UMAP data to start:
hv.Scatter(adata, A.obsm["umap"][0], [A.obsm["umap"][1], A.obs["type"]]).opts(
color=A.obs["type"]
)
To make it easier to access data we can also specify the dimensions as strings:
scatter = hv.Scatter(adata, "obsm.umap.0", ["obsm.umap.1", "obs.type"]).opts(
color="A.obs['type']"
)
scatter
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/holoviews/core/element.py:98: FutureWarning: Probably comparing to a dimension created from `Dimension.name`. This will not be supported in the future, please report as an issue.
return dimension in self.dimensions()
For an obs indexed dataset you can use the select method along the obs variables, e.g. we can select a specific type:
scatter.select({A.obs["type"]: 2}) # .select(dim(A.var["grp"]) == "a")
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/holoviews/core/element.py:98: FutureWarning: Probably comparing to a dimension created from `Dimension.name`. This will not be supported in the future, please report as an issue.
return dimension in self.dimensions()
We can also use the .iloc method to index along the obs dimension:
scatter.iloc[:50]
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/holoviews/core/element.py:98: FutureWarning: Probably comparing to a dimension created from `Dimension.name`. This will not be supported in the future, please report as an issue.
return dimension in self.dimensions()
We cannot can mix and match obs and var dimensions:
from holoviews.core.data.interface import DataError
try:
hv.Scatter(adata, A.obsm["umap"][0], A.var.index)
except DataError as e:
print(e)
AnnData Dataset in tabular mode must reference data along either the obs or the var axis, not both.
Gridded Data¶
AnnData can also hold gridded data and we can render that.
When rendering an Element that assumes continuous coordinates (e.g. Image) it will render the integer indices:
img = hv.Image(adata, [A.var.index, A.obs.index], [A.X[:, :]])
img
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/holoviews/core/dimension.py:1073: FutureWarning: Probably comparing to a dimension created from `Dimension.name`. This will not be supported in the future, please report as an issue.
return next(i for i, d in enumerate(dimensions) if d == dim)
When rendering into an element that assumes discrete values (e.g. HeatMap) the axes will be labelled:
hm = hv.HeatMap(adata, [A.obs.index, A.var.index], [A.X[:, :]])
hm.opts(responsive=True, height=800, xrotation=90)