Standardize metadata on-the-fly

This use cases runs on a LaminDB instance with populated CellType and Pathway registries. Make sure you run the GO Ontology notebook before executing this use case.

Here, we demonstrate how to standardize the metadata on-the-fly during cell type annotation and pathway enrichment analysis using these two registries.

For more information, see:

!lamin load use-cases-registries
→ connected lamindb: testuser1/use-cases-registries
import lamindb as ln
import bionty as bt
from lamin_usecases import datasets as ds
import scanpy as sc
import matplotlib.pyplot as plt
import celltypist
import gseapy as gp
→ connected lamindb: testuser1/use-cases-registries
sc.settings.set_figure_params(dpi=50, facecolor="white")
ln.context.uid = "hsPU1OENv0LS0000"
ln.context.track()
→ notebook imports: bionty==0.50.2 celltypist==1.6.3 gseapy==1.1.3 lamin_usecases==0.0.1 lamindb==0.76.8 matplotlib==3.9.2 scanpy==1.10.3
→ created Transform(uid='hsPU1OENv0LS0000') & created Run(started_at='2024-09-24 13:43:35 UTC')

An interferon-beta treated dataset

A small peripheral blood mononuclear cell dataset that is split into control and stimulated groups. The stimulated group was treated with interferon beta.

Let’s load the dataset and perform some preprocessing:

adata = ds.anndata_seurat_ifnb(preprocess=False, populate_registries=True)
adata

AnnData object with n_obs × n_vars = 13999 × 9942
    obs: 'stim'
    var: 'symbol'
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)
sc.pp.pca(adata, n_comps=20)
sc.pp.neighbors(adata, n_pcs=10)
sc.tl.umap(adata)

Analysis: cell type annotation using CellTypist

model = celltypist.models.Model.load(model="Immune_All_Low.pkl")
Hide code cell output
🔎 No available models. Downloading...
📜 Retrieving model list from server https://celltypist.cog.sanger.ac.uk/models/models.json
📚 Total models in list: 52
📂 Storing models in /home/runner/.celltypist/data/models
💾 Downloading model [1/52]: Immune_All_Low.pkl
💾 Downloading model [2/52]: Immune_All_High.pkl
💾 Downloading model [3/52]: Adult_COVID19_PBMC.pkl
💾 Downloading model [4/52]: Adult_CynomolgusMacaque_Hippocampus.pkl
💾 Downloading model [5/52]: Adult_Human_MTG.pkl
💾 Downloading model [6/52]: Adult_Human_PancreaticIslet.pkl
💾 Downloading model [7/52]: Adult_Human_PrefrontalCortex.pkl
💾 Downloading model [8/52]: Adult_Human_Skin.pkl
💾 Downloading model [9/52]: Adult_Mouse_Gut.pkl
💾 Downloading model [10/52]: Adult_Mouse_OlfactoryBulb.pkl
💾 Downloading model [11/52]: Adult_Pig_Hippocampus.pkl
💾 Downloading model [12/52]: Adult_RhesusMacaque_Hippocampus.pkl
💾 Downloading model [13/52]: Autopsy_COVID19_Lung.pkl
💾 Downloading model [14/52]: COVID19_HumanChallenge_Blood.pkl
💾 Downloading model [15/52]: COVID19_Immune_Landscape.pkl
💾 Downloading model [16/52]: Cells_Adult_Breast.pkl
💾 Downloading model [17/52]: Cells_Fetal_Lung.pkl
💾 Downloading model [18/52]: Cells_Human_Tonsil.pkl
💾 Downloading model [19/52]: Cells_Intestinal_Tract.pkl
💾 Downloading model [20/52]: Cells_Lung_Airway.pkl
💾 Downloading model [21/52]: Developing_Human_Brain.pkl
💾 Downloading model [22/52]: Developing_Human_Gonads.pkl
💾 Downloading model [23/52]: Developing_Human_Hippocampus.pkl
💾 Downloading model [24/52]: Developing_Human_Organs.pkl
💾 Downloading model [25/52]: Developing_Human_Thymus.pkl
💾 Downloading model [26/52]: Developing_Mouse_Brain.pkl
💾 Downloading model [27/52]: Developing_Mouse_Hippocampus.pkl
💾 Downloading model [28/52]: Fetal_Human_AdrenalGlands.pkl
💾 Downloading model [29/52]: Fetal_Human_Pancreas.pkl
💾 Downloading model [30/52]: Fetal_Human_Pituitary.pkl
💾 Downloading model [31/52]: Fetal_Human_Retina.pkl
💾 Downloading model [32/52]: Fetal_Human_Skin.pkl
💾 Downloading model [33/52]: Healthy_Adult_Heart.pkl
💾 Downloading model [34/52]: Healthy_COVID19_PBMC.pkl
💾 Downloading model [35/52]: Healthy_Human_Liver.pkl
💾 Downloading model [36/52]: Healthy_Mouse_Liver.pkl
💾 Downloading model [37/52]: Human_AdultAged_Hippocampus.pkl
💾 Downloading model [38/52]: Human_Colorectal_Cancer.pkl
💾 Downloading model [39/52]: Human_Developmental_Retina.pkl
💾 Downloading model [40/52]: Human_Embryonic_YolkSac.pkl
💾 Downloading model [41/52]: Human_IPF_Lung.pkl
💾 Downloading model [42/52]: Human_Longitudinal_Hippocampus.pkl
💾 Downloading model [43/52]: Human_Lung_Atlas.pkl
💾 Downloading model [44/52]: Human_PF_Lung.pkl
💾 Downloading model [45/52]: Human_Placenta_Decidua.pkl
💾 Downloading model [46/52]: Lethal_COVID19_Lung.pkl
💾 Downloading model [47/52]: Mouse_Dentate_Gyrus.pkl
💾 Downloading model [48/52]: Mouse_Isocortex_Hippocampus.pkl
💾 Downloading model [49/52]: Mouse_Postnatal_DentateGyrus.pkl
💾 Downloading model [50/52]: Mouse_Whole_Brain.pkl
💾 Downloading model [51/52]: Nuclei_Lung_Airway.pkl
💾 Downloading model [52/52]: Pan_Fetal_Human.pkl
predictions = celltypist.annotate(
    adata, model="Immune_All_Low.pkl", majority_voting=True
)
adata.obs["cell_type_celltypist"] = predictions.predicted_labels.majority_voting
🔬 Input data has 13999 cells and 9942 genes
🔗 Matching reference genes in the model
🧬 3700 features used for prediction
⚖️ Scaling input data
🖋️ Predicting labels
✅ Prediction done!
👀 Detected a neighborhood graph in the input object, will run over-clustering on the basis of it
⛓️ Over-clustering input data with resolution set to 10
🗳️ Majority voting the predictions
✅ Majority voting done!
adata.obs["cell_type_celltypist"] = bt.CellType.standardize(
    adata.obs["cell_type_celltypist"]
)
sc.pl.umap(
    adata,
    color=["cell_type_celltypist", "stim"],
    frameon=False,
    legend_fontsize=10,
    wspace=0.4,
)
... storing 'cell_type_celltypist' as categorical
_images/f5961d3c8ee234f52a56191c109c682475c3148a3fe89205b5cb18c4b2d21cbd.png

Analysis: Pathway enrichment analysis using Enrichr

This analysis is based on the GSEApy scRNA-seq Example.

First, we compute differentially expressed genes using a Wilcoxon test between stimulated and control cells.

# compute differentially expressed genes
sc.tl.rank_genes_groups(
    adata,
    groupby="stim",
    use_raw=False,
    method="wilcoxon",
    groups=["STIM"],
    reference="CTRL",
)

rank_genes_groups_df = sc.get.rank_genes_groups_df(adata, "STIM")
rank_genes_groups_df.head()
names scores logfoldchanges pvals pvals_adj
0 ISG15 99.456863 7.132767 0.0 0.0
1 ISG20 96.736786 5.074235 0.0 0.0
2 IFI6 94.973427 5.828862 0.0 0.0
3 IFIT3 92.482658 7.432466 0.0 0.0
4 IFIT1 90.699127 8.053555 0.0 0.0

Next, we filter out up/down-regulated differentially expressed gene sets:

degs_up = rank_genes_groups_df[
    (rank_genes_groups_df["logfoldchanges"] > 0)
    & (rank_genes_groups_df["pvals_adj"] < 0.05)
]
degs_dw = rank_genes_groups_df[
    (rank_genes_groups_df["logfoldchanges"] < 0)
    & (rank_genes_groups_df["pvals_adj"] < 0.05)
]

degs_up.shape, degs_dw.shape
((541, 5), (939, 5))

Run pathway enrichment analysis on DEGs and plot top 10 pathways:

enr_up = gp.enrichr(degs_up.names, gene_sets="GO_Biological_Process_2023").res2d
gp.dotplot(enr_up, figsize=(2, 3), title="Up", cmap=plt.cm.autumn_r);
enr_dw = gp.enrichr(degs_dw.names, gene_sets="GO_Biological_Process_2023").res2d
gp.dotplot(enr_dw, figsize=(2, 3), title="Down", cmap=plt.cm.winter_r);

Annotate & save dataset

gRegister new features and labels (check out more details here):

new_features = ln.Feature.from_df(adata.obs)
ln.save(new_features)
new_labels = [ln.ULabel(name=i) for i in adata.obs["stim"].unique()]
ln.save(new_labels)
features = ln.Feature.lookup()

Register dataset using a Artifact object:

artifact = ln.Artifact.from_anndata(
    adata,
    description="seurat_ifnb_activated_Bcells",
)
artifact.save()
Artifact(uid='uF9ExQw0SUypMy9j0000', is_latest=True, description='seurat_ifnb_activated_Bcells', suffix='.h5ad', type='dataset', size=215033772, hash='EeVzEqUMvi1XQcfHwHGEWL', _hash_type='sha1-fl', _accessor='AnnData', visibility=1, _key_is_virtual=True, storage_id=1, transform_id=1, run_id=1, created_by_id=1, updated_at='2024-09-24 13:46:43 UTC')
artifact.features._add_set_from_anndata(
    var_field=bt.Gene.symbol,
    organism="human", # optionally, globally set organism via bt.settings.organism = "human"
)

Querying metadata

artifact.describe()
Artifact(uid='uF9ExQw0SUypMy9j0000', is_latest=True, description='seurat_ifnb_activated_Bcells', suffix='.h5ad', type='dataset', size=215033772, hash='EeVzEqUMvi1XQcfHwHGEWL', _hash_type='sha1-fl', _accessor='AnnData', visibility=1, _key_is_virtual=True, updated_at='2024-09-24 13:46:44 UTC')
  Provenance
    .storage = '/home/runner/work/lamin-usecases/lamin-usecases/docs/use-cases-registries'
    .transform = 'Standardize metadata on-the-fly'
    .run = '2024-09-24 13:43:35 UTC'
    .created_by = 'testuser1'
  Labels
    .cell_types = 'effector memory CD8-positive, alpha-beta T cell', 'B cell', 'effector memory CD4-positive, alpha-beta T cell', 'dendritic cell, human', 'macrophage', 'natural killer cell', 'classical monocyte', 'non-classical monocyte', 'plasmacytoid dendritic cell', 'regulatory T cell', ...
    .ulabels = 'STIM', 'CTRL'
  Features
    'cell_type_celltypist' = 'effector memory CD8-positive, alpha-beta T cell', 'B cell', 'effector memory CD4-positive, alpha-beta T cell', 'dendritic cell, human', 'macrophage', 'natural killer cell', 'classical monocyte', 'non-classical monocyte', 'plasmacytoid dendritic cell', 'regulatory T cell', ...
    'stim' = 'STIM', 'CTRL'
  Feature sets
    'var' = 'CRB3', 'HSD3B7', 'PIK3CD', 'AGO3', 'SOBP', 'DKC1', 'TMED1', 'USP8', 'NGDN', 'TOMM40L', 'PCYT2', 'GPHN', 'ECI1', 'JAM2', 'HECW2', 'ITGA1', 'GTF2H5', 'PUM2', 'HTRA2', 'CYREN'
    'obs' = 'stim', 'cell_type_celltypist'
    'STIM-up-DEGs' = 'TAP1', 'DESI1', 'SCPEP1', 'ADAMDEC1', 'MLKL', 'RBM7', 'CD86', 'IGFBP4', 'NT5C3A', 'PRDX4', 'PSMA5', 'SIGLEC1', 'TAPBP'
    'STIM-down-DEGs' = 'CNPY2', 'SF3B1', 'YBX1', 'LST1', 'GRB2', 'MRPL20', 'PARL', 'NDUFA2', 'ATP6V0B', 'CDC42', 'ADRM1', 'TRA2B', 'SKP1'

Querying cell types

Querying for cell types contains “B cell” in the name:

bt.CellType.filter(name__contains="B cell").df().head()
uid name ontology_id abbr synonyms description source_id run_id created_by_id updated_at
id
1 ryEtgi1y B cell CL:0000236 None B cells|Cycling B cells|B-lymphocyte|B lymphoc... A Lymphocyte Of B Lineage That Is Capable Of B... 32 None 1 2024-09-24 13:43:26.863788+00:00
2 2EhFTUoZ follicular B cell CL:0000843 None follicular B-cell|follicular B lymphocyte|Fo B... A Resting Mature B Cell That Has The Phenotype... 32 None 1 2024-09-24 13:43:26.687576+00:00
3 4IowPafD germinal center B cell CL:0000844 None GC B cell|Germinal center B cells|GC B-lymphoc... A Rapidly Cycling Mature B Cell That Has Disti... 32 None 1 2024-09-24 13:43:26.720323+00:00
4 2cUPBtY8 memory B cell CL:0000787 None Age-associated B cells|memory B-cell|memory B-... A Memory B Cell Is A Mature B Cell That Is Lon... 32 None 1 2024-09-24 13:43:26.752507+00:00
5 3jdCg7zi naive B cell CL:0000788 None naive B lymphocyte|Naive B cells|naive B-cell|... A Naive B Cell Is A Mature B Cell That Has The... 32 None 1 2024-09-24 13:43:26.768333+00:00

Querying for all artifacts curated with a cell type:

celltypes = bt.CellType.lookup()
celltypes.plasmacytoid_dendritic_cell
CellType(uid='3JO0EdVd', name='plasmacytoid dendritic cell', ontology_id='CL:0000784', synonyms='plasmacytoid monocyte|T-associated plasma cell|DC2|IPC|plasmacytoid T cell|type 2 DC|lymphoid dendritic cell|interferon-producing cell|pDC', description='A Dendritic Cell Type Of Distinct Morphology, Localization, And Surface Marker Expression (Cd123-Positive) From Other Dendritic Cell Types And Associated With Early Stage Immune Responses, Particularly The Release Of Physiologically Abundant Amounts Of Type I Interferons In Response To Infection.', created_by_id=1, source_id=32, updated_at='2024-09-24 13:43:26 UTC')
ln.Artifact.filter(cell_types=celltypes.plasmacytoid_dendritic_cell).df()
uid version is_latest description key suffix type size hash n_objects n_observations _hash_type _accessor visibility _key_is_virtual storage_id transform_id run_id created_by_id updated_at
id
1 uF9ExQw0SUypMy9j0000 None True seurat_ifnb_activated_Bcells None .h5ad dataset 215033772 EeVzEqUMvi1XQcfHwHGEWL None None sha1-fl AnnData 1 True 1 1 1 1 2024-09-24 13:46:44.459035+00:00

Querying pathways

Querying for pathways contains “interferon-beta” in the name:

bt.Pathway.filter(name__contains="interferon-beta").df()
uid name ontology_id abbr synonyms description source_id run_id created_by_id updated_at
id
684 1l4z0v8W cellular response to interferon-beta GO:0035458 None cellular response to fiblaferon|cellular respo... Any Process That Results In A Change In State ... 85 None 1 2024-09-24 13:42:41.481829+00:00
2130 1NzHDJDi negative regulation of interferon-beta production GO:0032688 None down regulation of interferon-beta production|... Any Process That Stops, Prevents, Or Reduces T... 85 None 1 2024-09-24 13:42:41.541619+00:00
3127 3x0xmK1y positive regulation of interferon-beta production GO:0032728 None up-regulation of interferon-beta production|up... Any Process That Activates Or Increases The Fr... 85 None 1 2024-09-24 13:42:41.585407+00:00
4334 54R2a0el regulation of interferon-beta production GO:0032648 None regulation of IFN-beta production Any Process That Modulates The Frequency, Rate... 85 None 1 2024-09-24 13:42:41.638823+00:00
4953 3VZq4dMe response to interferon-beta GO:0035456 None response to fiblaferon|response to fibroblast ... Any Process That Results In A Change In State ... 85 None 1 2024-09-24 13:42:41.665775+00:00

Query pathways from a gene:

bt.Pathway.filter(genes__symbol="KIR2DL1").df()
uid name ontology_id abbr synonyms description source_id run_id created_by_id updated_at
id
1346 7S7qlEkG immune response-inhibiting cell surface recept... GO:0002767 None immune response-inhibiting cell surface recept... The Series Of Molecular Signals Initiated By A... 85 None 1 2024-09-24 13:42:41.508190+00:00

Query artifacts from a pathway:

ln.Artifact.filter(feature_sets__pathways__name__icontains="interferon-beta").first()
Artifact(uid='uF9ExQw0SUypMy9j0000', is_latest=True, description='seurat_ifnb_activated_Bcells', suffix='.h5ad', type='dataset', size=215033772, hash='EeVzEqUMvi1XQcfHwHGEWL', _hash_type='sha1-fl', _accessor='AnnData', visibility=1, _key_is_virtual=True, storage_id=1, transform_id=1, run_id=1, created_by_id=1, updated_at='2024-09-24 13:46:44 UTC')

Query featuresets from a pathway to learn from which geneset this pathway was computed:

pathway = bt.Pathway.get(ontology_id="GO:0035456")
pathway
Pathway(uid='3VZq4dMe', name='response to interferon-beta', ontology_id='GO:0035456', synonyms='response to fiblaferon|response to fibroblast interferon|response to interferon beta', description='Any Process That Results In A Change In State Or Activity Of A Cell Or An Organism (In Terms Of Movement, Secretion, Enzyme Production, Gene Expression, Etc.) As A Result Of An Interferon-Beta Stimulus. Interferon-Beta Is A Type I Interferon.', created_by_id=1, source_id=85, updated_at='2024-09-24 13:42:41 UTC')
degs = ln.FeatureSet.get(pathways__ontology_id=pathway.ontology_id)

Now we can get the list of genes that are differentially expressed and belong to this pathway:

contributing_genes = pathway.genes.all() & degs.genes.all()
contributing_genes.list("symbol")
['IFI16',
 'BST2',
 'IFITM2',
 'CALM1',
 'OAS1',
 'IFITM3',
 'XAF1',
 'IFITM1',
 'IRF1',
 'PLSCR1',
 'PNPT1',
 'STAT1',
 'AIM2',
 'MNDA',
 'SHFL']
# clean up test instance
!lamin delete --force use-cases-registries
!rm -r ./use-cases-registries
Hide code cell output
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.11.10/x64/bin/lamin", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/rich_click/rich_command.py", line 367, in __call__
    return super().__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/rich_click/rich_command.py", line 152, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/lamin_cli/__main__.py", line 205, in delete
    return delete(instance, force=force)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/lamindb_setup/_delete.py", line 102, in delete
    n_objects = check_storage_is_empty(
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/lamindb_setup/core/upath.py", line 776, in check_storage_is_empty
    raise InstanceNotEmpty(message)
lamindb_setup.core.upath.InstanceNotEmpty: Storage /home/runner/work/lamin-usecases/lamin-usecases/docs/use-cases-registries/.lamindb contains 1 objects ('_is_initialized' ignored) - delete them prior to deleting the instance