AnnDataΒΆ

import holoviews as hv

from hv_anndata.interface import ACCESSOR as 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)

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

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")

We can also use the .iloc method to index along the obs dimension:

scatter.iloc[:50]

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[:, :]])
img

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[:, :]])

hm.opts(responsive=True, height=800, xrotation=90)