Analyst’s view#
Here, we’ll take an analysts-centric view of typical file transformations.
If exploring more generally, read this first: Bird’s eye view.
Show code cell content
# a lamindb instance containing Bionty schema
!lamin init --storage ./analysis-usecase --schema bionty
💡 creating schemas: core==0.45.2 bionty==0.29.3
🌱 saved: User(id='DzTjkKse', handle='testuser1', email='testuser1@lamin.ai', name='Test User1', updated_at=2023-08-12 05:45:34)
🌱 saved: Storage(id='arniDE1n', root='/home/runner/work/lamin-usecases/lamin-usecases/docs/analysis-usecase', type='local', updated_at=2023-08-12 05:45:34, created_by_id='DzTjkKse')
✅ loaded instance: testuser1/analysis-usecase
💡 did not register local instance on hub (if you want, call `lamin register`)
import lamindb as ln
import lnschema_bionty as lb
lb.settings.species = "human" # globally set species
lb.settings.auto_save_parents = False
✅ loaded instance: testuser1/analysis-usecase (lamindb 0.50.3)
🌱 set species: Species(id='uHJU', name='human', taxon_id=9606, scientific_name='homo_sapiens', updated_at=2023-08-12 05:45:35, bionty_source_id='Bwpi', created_by_id='DzTjkKse')
ln.track()
💡 notebook imports: lamindb==0.50.3 lnschema_bionty==0.29.3
🌱 saved: Transform(id='eNef4Arw8nNMz8', name='Analyst's view', short_name='analysis-flow', stem_id='eNef4Arw8nNM', version='0', type=notebook, updated_at=2023-08-12 05:45:35, created_by_id='DzTjkKse')
🌱 saved: Run(id='7FkA8RclVLpLg2ksDtOx', run_at=2023-08-12 05:45:35, transform_id='eNef4Arw8nNMz8', created_by_id='DzTjkKse')
Track cell types, tissues and diseases#
We fetch an example dataset from LaminDB that has a few cell type, tissue and disease annotations:
Show code cell content
adata = ln.dev.datasets.anndata_with_obs()
adata
AnnData object with n_obs × n_vars = 40 × 100
obs: 'cell_type', 'cell_type_id', 'tissue', 'disease'
adata.var_names[:5]
Index(['ENSG00000000003', 'ENSG00000000005', 'ENSG00000000419',
'ENSG00000000457', 'ENSG00000000460'],
dtype='object')
adata.obs[["tissue", "cell_type", "disease"]].value_counts()
tissue cell_type disease
brain my new cell type Alzheimer disease 10
heart hepatocyte cardiac ventricle disorder 10
kidney T cell chronic kidney disease 10
liver hematopoietic stem cell liver lymphoma 10
Name: count, dtype: int64
Register biological metadata and link to the dataset#
As a first step, we register the Anndata object with LaminDB using from_anndata()
:
file = ln.File.from_anndata(
adata, key="mini_anndata_with_obs.h5ad", var_ref=lb.Gene.ensembl_gene_id
)
💡 file will be copied to default storage upon `save()` with key 'mini_anndata_with_obs.h5ad'
💡 parsing feature names of X stored in slot 'var'
💡 using global setting species = human
✅ validated 99 Gene records from Bionty on ensembl_gene_id: ENSG00000000003, ENSG00000000005, ENSG00000000419, ENSG00000000457, ENSG00000000460, ENSG00000000938, ENSG00000000971, ENSG00000001036, ENSG00000001084, ENSG00000001167, ENSG00000001460, ENSG00000001461, ENSG00000001497, ENSG00000001561, ENSG00000001617, ENSG00000001626, ENSG00000001629, ENSG00000001630, ENSG00000001631, ENSG00000002016, ...
🌱 linked: FeatureSet(id='LAwnc8Oalunw5OzdvrFA', n=99, type='float', registry='bionty.Gene', hash='fHbDaAAmJse48vnUQh9C', created_by_id='DzTjkKse')
💡 parsing feature names of slot 'obs'
🔶 did not validate 4 Feature records for names: cell_type, cell_type_id, tissue, disease
🔶 ignoring non-validated features: cell_type,cell_type_id,tissue,disease
🔶 no validated features, skip creating feature set
file.save()
🌱 saved 1 feature set for slot: ['var']
🌱 storing file 'JKI2YanhVazcIIdkBgLm' with key 'mini_anndata_with_obs.h5ad'
cell_types = lb.CellType.from_values(adata.obs.cell_type, lb.CellType.name)
tissues = lb.Tissue.from_values(adata.obs.tissue, lb.Tissue.name)
diseases = lb.Disease.from_values(adata.obs.disease, lb.Disease.name)
Show code cell output
✅ validated 3 CellType records from Bionty on name: T cell, hematopoietic stem cell, hepatocyte
🔶 did not validate 1 CellType record for name: my new cell type
✅ validated 4 Tissue records from Bionty on name: kidney, liver, heart, brain
✅ validated 4 Disease records from Bionty on name: chronic kidney disease, liver lymphoma, cardiac ventricle disorder, Alzheimer disease
All of these look good and contain no typos, let’s save them to their registries:
ln.save(cell_types)
ln.save(tissues)
ln.save(diseases)
We also need some features to bucket these labels:
ln.Feature(name="cell_type", type="category").save()
ln.Feature(name="tissue", type="category").save()
ln.Feature(name="disease", type="category").save()
Link labels against the file:
file.add_labels(cell_types)
file.add_labels(tissues)
file.add_labels(diseases)
Show code cell output
🌱 linked labels 'T cell', 'hematopoietic stem cell', 'hepatocyte', 'my new cell type' to feature 'cell_type', linked feature 'cell_type' to registry 'bionty.CellType'
🌱 created feature set for slot 'external'
🌱 linked labels 'kidney', 'liver', 'heart', 'brain' to feature 'tissue', linked feature 'tissue' to registry 'bionty.Tissue'
🌱 linked feature tissue to feature set FeatureSet(id='gpOL9Vyi1uEnPmyVQmET', n=2, registry='core.Feature', hash='t0L1kryg2Sm0mNr5FoKJ', updated_at=2023-08-12 05:45:39, modality_id='xe4XJ5yC', created_by_id='DzTjkKse')
🌱 linked labels 'chronic kidney disease', 'liver lymphoma', 'cardiac ventricle disorder', 'Alzheimer disease' to feature 'disease', linked feature 'disease' to registry 'bionty.Disease'
🌱 linked feature disease to feature set FeatureSet(id='gpOL9Vyi1uEnPmyVQmET', n=3, registry='core.Feature', hash='t0L1kryg2Sm0mNr5FoKJ', updated_at=2023-08-12 05:45:39, modality_id='xe4XJ5yC', created_by_id='DzTjkKse')
file.describe()
💡 File(id=JKI2YanhVazcIIdkBgLm, key=mini_anndata_with_obs.h5ad, suffix=.h5ad, accessor=AnnData, description=None, version=None, size=46992, hash=IJORtcQUSS11QBqD-nTD0A, hash_type=md5, created_at=2023-08-12 05:45:38.482959+00:00, updated_at=2023-08-12 05:45:38.482983+00:00)
Provenance:
🗃️ storage: Storage(id='arniDE1n', root='/home/runner/work/lamin-usecases/lamin-usecases/docs/analysis-usecase', type='local', updated_at=2023-08-12 05:45:34, created_by_id='DzTjkKse')
📎 initial_version: None
📔 transform: Transform(id='eNef4Arw8nNMz8', name='Analyst's view', short_name='analysis-flow', stem_id='eNef4Arw8nNM', version='0', type='notebook', updated_at=2023-08-12 05:45:38, created_by_id='DzTjkKse')
🚗 run: Run(id='7FkA8RclVLpLg2ksDtOx', run_at=2023-08-12 05:45:35, transform_id='eNef4Arw8nNMz8', created_by_id='DzTjkKse')
👤 created_by: User(id='DzTjkKse', handle='testuser1', email='testuser1@lamin.ai', name='Test User1', updated_at=2023-08-12 05:45:34)
Features:
🗺️ var (X):
🔗 index (99, bionty.Gene.id): ['rzd9Z8GZpmpY', '53yek5j7MIEm', 'WQ2WkyuK7amp', 'ZhSomSek7PpB', '25ydmnaZhOTY'...]
🗺️ external:
🔗 cell_type (4, bionty.CellType): ['my new cell type', 'hematopoietic stem cell', 'T cell', 'hepatocyte']
🔗 disease (4, bionty.Disease): ['Alzheimer disease', 'cardiac ventricle disorder', 'chronic kidney disease', 'liver lymphoma']
🔗 tissue (4, bionty.Tissue): ['kidney', 'brain', 'liver', 'heart']
file.view_lineage()
Examine the currently available cell types and tissues:
lb.CellType.filter().df()
Show code cell output
name | ontology_id | abbr | synonyms | description | bionty_source_id | updated_at | created_by_id | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
BsWVPq4Z | my new cell type | None | None | None | None | None | 2023-08-12 05:45:39 | DzTjkKse |
m91LZBDZ | hematopoietic stem cell | CL:0000037 | None | blood forming stem cell|hemopoietic stem cell|HSC | A Stem Cell From Which All Cells Of The Lympho... | DSKE | 2023-08-12 05:45:39 | DzTjkKse |
BxNjby0x | T cell | CL:0000084 | None | T-lymphocyte|T-cell|T lymphocyte | A Type Of Lymphocyte Whose Defining Characteri... | DSKE | 2023-08-12 05:45:39 | DzTjkKse |
J7hHC8SK | hepatocyte | CL:0000182 | None | None | The Main Structural Component Of The Liver. Th... | DSKE | 2023-08-12 05:45:39 | DzTjkKse |
lb.Tissue.filter().df()
Show code cell output
name | ontology_id | abbr | synonyms | description | bionty_source_id | updated_at | created_by_id | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
j9lTWyWV | kidney | UBERON:0002113 | None | None | A Paired Organ Of The Urinary Tract Which Has ... | yqqb | 2023-08-12 05:45:39 | DzTjkKse |
7HcGzG0l | brain | UBERON:0000955 | None | None | The Brain Is The Center Of The Nervous System ... | yqqb | 2023-08-12 05:45:39 | DzTjkKse |
HHKnN309 | liver | UBERON:0002107 | None | None | An Exocrine Gland Which Secretes Bile And Func... | yqqb | 2023-08-12 05:45:39 | DzTjkKse |
sm45H0wI | heart | UBERON:0000948 | None | vertebrate heart|chambered heart | A Myogenic Muscular Circulatory Organ Found In... | yqqb | 2023-08-12 05:45:39 | DzTjkKse |
Processing the dataset#
To track our data transformation we create a new Transform
of type “pipeline”:
transform = ln.Transform(
name="Subset to T-cells and liver lymphoma", version="0.1.0", type="pipeline"
)
Set the current tracking to the new transform:
ln.track(transform)
🌱 saved: Transform(id='n3ZZ1Fwkcrn85d', name='Subset to T-cells and liver lymphoma', stem_id='n3ZZ1Fwkcrn8', version='0.1.0', type='pipeline', updated_at=2023-08-12 05:45:40, created_by_id='DzTjkKse')
🌱 saved: Run(id='Pylrx9Yqd0hdXi0uTzCc', run_at=2023-08-12 05:45:40, transform_id='n3ZZ1Fwkcrn85d', created_by_id='DzTjkKse')
Get a backed AnnData object#
file = ln.File.filter(key="mini_anndata_with_obs.h5ad").one()
adata = file.backed()
adata
💡 adding file JKI2YanhVazcIIdkBgLm as input for run Pylrx9Yqd0hdXi0uTzCc, adding parent transform eNef4Arw8nNMz8
AnnDataAccessor object with n_obs × n_vars = 40 × 100
constructed for the AnnData object mini_anndata_with_obs.h5ad
obs: ['_index', 'cell_type', 'cell_type_id', 'disease', 'tissue']
var: ['_index']
adata.obs[["cell_type", "disease"]].value_counts()
cell_type disease
T cell chronic kidney disease 10
hematopoietic stem cell liver lymphoma 10
hepatocyte cardiac ventricle disorder 10
my new cell type Alzheimer disease 10
Name: count, dtype: int64
Subset dataset to specific cell types and diseases#
Create the subset:
subset_obs = adata.obs.cell_type.isin(["T cell", "hematopoietic stem cell"]) & (
adata.obs.disease.isin(["liver lymphoma", "chronic kidney disease"])
)
adata_subset = adata[subset_obs]
adata_subset
AnnDataAccessorSubset object with n_obs × n_vars = 20 × 100
obs: ['_index', 'cell_type', 'cell_type_id', 'disease', 'tissue']
var: ['_index']
adata_subset.obs[["cell_type", "disease"]].value_counts()
cell_type disease
T cell chronic kidney disease 10
hematopoietic stem cell liver lymphoma 10
Name: count, dtype: int64
This subset can now be registered:
file_subset = ln.File.from_anndata(
adata_subset.to_memory(),
key="subset/mini_anndata_with_obs.h5ad",
var_ref=lb.Gene.ensembl_gene_id,
)
/opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages/anndata/_core/anndata.py:1840: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.
utils.warn_names_duplicates("var")
💡 file will be copied to default storage upon `save()` with key 'subset/mini_anndata_with_obs.h5ad'
💡 parsing feature names of X stored in slot 'var'
💡 using global setting species = human
✅ validated 99 Gene records on ensembl_gene_id: ENSG00000000003, ENSG00000000005, ENSG00000000419, ENSG00000000457, ENSG00000000460, ENSG00000000938, ENSG00000000971, ENSG00000001036, ENSG00000001084, ENSG00000001167, ENSG00000001460, ENSG00000001461, ENSG00000001497, ENSG00000001561, ENSG00000001617, ENSG00000001626, ENSG00000001629, ENSG00000001630, ENSG00000001631, ENSG00000002016, ...
✅ loaded FeatureSet(id='LAwnc8Oalunw5OzdvrFA', n=99, type='float', registry='bionty.Gene', hash='fHbDaAAmJse48vnUQh9C', updated_at=2023-08-12 05:45:38, created_by_id='DzTjkKse')
🌱 linked: FeatureSet(id='LAwnc8Oalunw5OzdvrFA', n=99, type='float', registry='bionty.Gene', hash='fHbDaAAmJse48vnUQh9C', updated_at=2023-08-12 05:45:38, created_by_id='DzTjkKse')
💡 parsing feature names of slot 'obs'
✅ validated 3 Feature records on name: cell_type, disease, tissue
🔶 did not validate 1 Feature record for name: cell_type_id
🔶 ignoring non-validated features: cell_type_id
🌱 linked: FeatureSet(id='qWycs1N8viJD8U2dKYWi', n=3, registry='core.Feature', hash='QcgNfF5sdGaF8bHA767e', created_by_id='DzTjkKse')
file_subset.save()
🌱 saved 2 feature sets for slots: ['var', 'obs']
🌱 storing file 'NZsbppFOZsK18XpxUJxv' with key 'subset/mini_anndata_with_obs.h5ad'
Add labels to features, all of them validate:
cell_types = lb.CellType.from_values(adata.obs.cell_type, lb.CellType.name)
tissues = lb.Tissue.from_values(adata.obs.tissue, lb.Tissue.name)
diseases = lb.Disease.from_values(adata.obs.disease, lb.Disease.name)
file_subset.add_labels(cell_types)
file_subset.add_labels(tissues)
file_subset.add_labels(diseases)
Show code cell output
✅ validated 4 CellType records on name: T cell, hematopoietic stem cell, hepatocyte, my new cell type
✅ validated 4 Tissue records on name: brain, heart, kidney, liver
✅ validated 4 Disease records on name: Alzheimer disease, cardiac ventricle disorder, chronic kidney disease, liver lymphoma
🌱 linked labels 'T cell', 'hematopoietic stem cell', 'hepatocyte', 'my new cell type' to feature 'cell_type'
🌱 linked labels 'brain', 'heart', 'kidney', 'liver' to feature 'tissue'
🌱 linked labels 'Alzheimer disease', 'cardiac ventricle disorder', 'chronic kidney disease', 'liver lymphoma' to feature 'disease'
file_subset.describe()
💡 File(id=NZsbppFOZsK18XpxUJxv, key=subset/mini_anndata_with_obs.h5ad, suffix=.h5ad, accessor=AnnData, description=None, version=None, size=38992, hash=RgGUx7ndRplZZSmalTAWiw, hash_type=md5, created_at=2023-08-12 05:45:40.279907+00:00, updated_at=2023-08-12 05:45:40.279931+00:00)
Provenance:
🗃️ storage: Storage(id='arniDE1n', root='/home/runner/work/lamin-usecases/lamin-usecases/docs/analysis-usecase', type='local', updated_at=2023-08-12 05:45:34, created_by_id='DzTjkKse')
📎 initial_version: None
🧩 transform: Transform(id='n3ZZ1Fwkcrn85d', name='Subset to T-cells and liver lymphoma', stem_id='n3ZZ1Fwkcrn8', version='0.1.0', type='pipeline', updated_at=2023-08-12 05:45:40, created_by_id='DzTjkKse')
🚗 run: Run(id='Pylrx9Yqd0hdXi0uTzCc', run_at=2023-08-12 05:45:40, transform_id='n3ZZ1Fwkcrn85d', created_by_id='DzTjkKse')
👤 created_by: User(id='DzTjkKse', handle='testuser1', email='testuser1@lamin.ai', name='Test User1', updated_at=2023-08-12 05:45:34)
Features:
🗺️ var (X):
🔗 index (99, bionty.Gene.id): ['rzd9Z8GZpmpY', '53yek5j7MIEm', 'WQ2WkyuK7amp', 'ZhSomSek7PpB', '25ydmnaZhOTY'...]
🗺️ obs (metadata):
🔗 cell_type (4, bionty.CellType): ['my new cell type', 'hematopoietic stem cell', 'T cell', 'hepatocyte']
🔗 disease (4, bionty.Disease): ['Alzheimer disease', 'cardiac ventricle disorder', 'chronic kidney disease', 'liver lymphoma']
🔗 tissue (4, bionty.Tissue): ['heart', 'brain', 'liver', 'kidney']
Examine data lineage#
Common questions that might arise are:
Which h5ad file is in the
subset
subfolder?Which notebook ingested this file?
By whom?
And which file is its parent?
Let’s answer this using LaminDB:
Query a subsetted .h5ad
file containing “hematopoietic stem cell” and “T cell” to learn which h5ad file is in the subset
subfolder:
cell_types_bt_lookup = lb.CellType.lookup()
my_subset = ln.File.filter(
suffix=".h5ad",
key__startswith="subset",
cell_types__in=[
cell_types_bt_lookup.hematopoietic_stem_cell,
cell_types_bt_lookup.t_cell,
],
).first()
my_subset.view_lineage()
Show code cell content
!lamin delete analysis-usecase
!rm -r ./analysis-usecase
💡 deleting instance testuser1/analysis-usecase
✅ deleted instance settings file: /home/runner/.lamin/instance--testuser1--analysis-usecase.env
✅ instance cache deleted
✅ deleted '.lndb' sqlite file
🔶 consider manually delete your stored data: /home/runner/work/lamin-usecases/lamin-usecases/docs/analysis-usecase