{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# AnnData" ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", "\n", "from hv_anndata.interface import ACCESSOR as A\n", "from hv_anndata.interface import register\n", "\n", "register()\n", "\n", "hv.extension(\"bokeh\")" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "## Create synthetic data" ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": {}, "outputs": [], "source": [ "from string import ascii_lowercase\n", "\n", "import numpy as np\n", "import pandas as pd\n", "import scipy.sparse as sp\n", "from anndata import AnnData\n", "\n", "gen = np.random.default_rng()\n", "x = gen.random((100, 50), dtype=np.float32)\n", "layers = dict(a=sp.random(100, 50, format=\"csr\"))\n", "obs = pd.DataFrame(\n", " dict(type=gen.integers(0, 3, size=100)),\n", " index=pd.Series(range(100)).astype(str).apply(lambda v: \"cell-\" + v),\n", ")\n", "var_grp = pd.Categorical(\n", " gen.integers(0, 6, size=50), categories=list(ascii_lowercase[:5])\n", ")\n", "var = pd.DataFrame(\n", " dict(grp=var_grp),\n", " index=pd.Series(range(50)).astype(str).apply(lambda v: \"gene-\" + v),\n", ")\n", "obsm = dict(umap=gen.random((100, 2)))\n", "varp = dict(cons=sp.csr_array(sp.random(50, 50)))\n", "adata = AnnData(x, obs, var, layers=layers, obsm=obsm, varm={}, obsp={}, varp=varp)" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "## Tabular mode" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "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.\n", "\n", "Let us visualize the UMAP data to start:" ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [], "source": [ "hv.Scatter(adata, A.obsm[\"umap\"][0], [A.obsm[\"umap\"][1], A.obs[\"type\"]]).opts(\n", " color=A.obs[\"type\"]\n", ")" ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "To make it easier to access data we can also specify the dimensions as strings:" ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "scatter = hv.Scatter(adata, \"obsm.umap.0\", [\"obsm.umap.1\", \"obs.type\"]).opts(\n", " color=\"A.obs['type']\"\n", ")\n", "\n", "scatter" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "For an `obs` indexed dataset you can use the select method along the obs variables, e.g. we can select a specific type:" ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": {}, "outputs": [], "source": [ "scatter.select({A.obs[\"type\"]: 2}) # .select(dim(A.var[\"grp\"]) == \"a\")" ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "We can also use the `.iloc` method to index along the obs dimension:" ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "scatter.iloc[:50]" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "We cannot can mix and match `obs` and `var` dimensions:" ] }, { "cell_type": "code", "execution_count": null, "id": "14", "metadata": {}, "outputs": [], "source": [ "from holoviews.core.data.interface import DataError\n", "\n", "try:\n", " hv.Scatter(adata, A.obsm[\"umap\"][0], A.var[\"index\"])\n", "except DataError as e:\n", " print(e)" ] }, { "cell_type": "markdown", "id": "15", "metadata": {}, "source": [ "## Gridded Data\n", "\n", "AnnData can also hold gridded data and we can render that.\n", "\n", "When rendering an Element that assumes continuous coordinates (e.g. `Image`) it will render the integer indices:" ] }, { "cell_type": "code", "execution_count": null, "id": "16", "metadata": {}, "outputs": [], "source": [ "img = hv.Image(adata, [A.var[\"index\"], A.obs[\"index\"]], [A[:, :]])\n", "img" ] }, { "cell_type": "markdown", "id": "17", "metadata": {}, "source": [ "When rendering into an element that assumes discrete values (e.g. HeatMap) the axes will be labelled:" ] }, { "cell_type": "code", "execution_count": null, "id": "18", "metadata": {}, "outputs": [], "source": [ "hm = hv.HeatMap(adata, [A.obs[\"index\"], A.var[\"index\"]], [A[:, :]])\n", "\n", "hm.opts(responsive=True, height=800, xrotation=90)" ] }, { "cell_type": "code", "execution_count": null, "id": "19", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.5" } }, "nbformat": 4, "nbformat_minor": 5 }