Violin

import holoviews as hv

from hv_anndata.interface import register

register()

hv.extension("bokeh")
import anndata as ad
import pooch
import scanpy as sc
EXAMPLE_DATA = pooch.create(
    path=pooch.os_cache("scverse_tutorials"),
    base_url="doi:10.6084/m9.figshare.22716739.v1/",
)
EXAMPLE_DATA.load_registry_from_doi()
samples = {
    "s1d1": "s1d1_filtered_feature_bc_matrix.h5",
    "s1d3": "s1d3_filtered_feature_bc_matrix.h5",
}
adatas = {}

for sample_id, filename in samples.items():
    path = EXAMPLE_DATA.fetch(filename)
    sample_adata = sc.read_10x_h5(path)
    sample_adata.var_names_make_unique()
    adatas[sample_id] = sample_adata

adata = ad.concat(adatas, label="sample")
adata.obs_names_make_unique()
print(adata.obs["sample"].value_counts())
adata
Downloading file 's1d1_filtered_feature_bc_matrix.h5' from 'doi:10.6084/m9.figshare.22716739.v1/s1d1_filtered_feature_bc_matrix.h5' to '/home/docs/.cache/scverse_tutorials'.
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/scanpy/readwrite.py:248: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.
  adata = adata.copy()
Downloading file 's1d3_filtered_feature_bc_matrix.h5' from 'doi:10.6084/m9.figshare.22716739.v1/s1d3_filtered_feature_bc_matrix.h5' to '/home/docs/.cache/scverse_tutorials'.
sample
s1d1    8785
s1d3    8340
Name: count, dtype: int64
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/scanpy/readwrite.py:248: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.
  adata = adata.copy()
/tmp/ipykernel_1872/3491096135.py:13: UserWarning: Observation names are not unique. To make them unique, call `.obs_names_make_unique`.
  adata = ad.concat(adatas, label="sample")
AnnData object with n_obs × n_vars = 17125 × 36601
    obs: 'sample'
    layers: None (.X)
adata.var["mt"] = adata.var_names.str.startswith("MT-")
adata.var["ribo"] = adata.var_names.str.startswith(("RPS", "RPL"))
adata.var["hb"] = adata.var_names.str.contains("^HB[^(P)]")

sc.pp.calculate_qc_metrics(
    adata, qc_vars=["mt", "ribo", "hb"], inplace=True, log1p=True
)
/home/docs/.local/share/hatch/env/virtual/hv-anndata/STk7F69l/docs/lib/python3.13/site-packages/numba/cpython/hashing.py:477: UserWarning: FNV hashing is not implemented in Numba. See PEP 456 https://www.python.org/dev/peps/pep-0456/ for rationale over not using FNV. Numba will continue to work, but hashes for built in types will be computed using siphash24. This will permit e.g. dictionaries to continue to behave as expected, however anything relying on the value of the hash opposed to hash as a derived property is likely to not work as expected.
  warnings.warn(msg)
sc.pl.violin(
    adata,
    ["n_genes_by_counts", "total_counts", "pct_counts_mt"],
    jitter=0.4,
    multi_panel=True,
)
violins = [
    hv.Violin(adata, vdims=i).opts(
        ylabel="Value",
        title=i.split(".")[-1],  # drop the 'obs.'
        show_grid=True,
        ylim=(0, None),
    )
    for i in ["obs.n_genes_by_counts", "obs.total_counts", "obs.pct_counts_mt"]
]
hv.Layout(violins).opts(axiswise=True)