`__.
58 |
59 | """
60 |
61 | import secrets
62 | import string
63 |
64 |
65 | def base64(n_char: int) -> str:
66 | """Random Base64 string."""
67 | alphabet = string.digits + string.ascii_letters.swapcase() + "_" + "-"
68 | uid = "".join(secrets.choice(alphabet) for i in range(n_char))
69 | return uid
70 |
71 |
72 | def base62(n_char: int) -> str:
73 | """Random Base62 string."""
74 | alphabet = string.digits + string.ascii_letters.swapcase()
75 | uid = "".join(secrets.choice(alphabet) for i in range(n_char))
76 | return uid
77 |
78 |
79 | def base26(n_char: int):
80 | """ASCII lowercase."""
81 | alphabet = string.ascii_lowercase
82 | uid = "".join(secrets.choice(alphabet) for i in range(n_char))
83 | return uid
84 |
85 |
86 | def base62_4() -> str:
87 | return base62(4)
88 |
89 |
90 | def base62_8() -> str:
91 | """Random Base62 string of length 8."""
92 | return base62(8)
93 |
94 |
95 | def base62_12() -> str:
96 | """Random Base62 string of length 12."""
97 | return base62(12)
98 |
99 |
100 | def base62_16() -> str:
101 | """Random Base62 string of length 16."""
102 | return base62(16)
103 |
104 |
105 | def base62_20() -> str:
106 | """Random Base62 string of length 20."""
107 | return base62(20)
108 |
109 |
110 | def base62_24() -> str:
111 | """Random Base62 string of length 24."""
112 | return base62(24)
113 |
--------------------------------------------------------------------------------
/lamindb/examples/datasets/__init__.py:
--------------------------------------------------------------------------------
1 | """Example datasets.
2 |
3 | The mini immuno dataset
4 | -----------------------
5 |
6 | .. autosummary::
7 | :toctree: .
8 |
9 | mini_immuno
10 |
11 | Small in-memory datasets
12 | ------------------------
13 |
14 | .. autofunction:: anndata_with_obs
15 |
16 | Files
17 | -----
18 |
19 | .. autofunction:: file_fcs
20 | .. autofunction:: file_fcs_alpert19
21 | .. autofunction:: file_tsv_rnaseq_nfcore_salmon_merged_gene_counts
22 | .. autofunction:: file_jpg_paradisi05
23 | .. autofunction:: file_tiff_suo22
24 | .. autofunction:: file_fastq
25 | .. autofunction:: file_bam
26 | .. autofunction:: file_mini_csv
27 |
28 | Directories
29 | -----------
30 |
31 | .. autofunction:: dir_scrnaseq_cellranger
32 | .. autofunction:: dir_iris_images
33 |
34 | Dictionary, Dataframe, AnnData, MuData, SpatialData
35 | ----------------------------------------------------
36 |
37 | .. autofunction:: dict_cellxgene_uns
38 | .. autofunction:: df_iris
39 | .. autofunction:: df_iris_in_meter
40 | .. autofunction:: df_iris_in_meter_study1
41 | .. autofunction:: df_iris_in_meter_study2
42 | .. autofunction:: anndata_mouse_sc_lymph_node
43 | .. autofunction:: anndata_human_immune_cells
44 | .. autofunction:: anndata_pbmc68k_reduced
45 | .. autofunction:: anndata_file_pbmc68k_test
46 | .. autofunction:: anndata_pbmc3k_processed
47 | .. autofunction:: anndata_with_obs
48 | .. autofunction:: anndata_suo22_Visium10X
49 | .. autofunction:: mudata_papalexi21_subset
50 | .. autofunction:: schmidt22_crispra_gws_IFNG
51 | .. autofunction:: schmidt22_perturbseq
52 | .. autofunction:: spatialdata_blobs
53 |
54 | Other
55 | -----
56 |
57 | .. autofunction:: fake_bio_notebook_titles
58 | """
59 |
60 | from . import mini_immuno
61 | from ._core import (
62 | anndata_file_pbmc68k_test,
63 | anndata_human_immune_cells,
64 | anndata_mouse_sc_lymph_node,
65 | anndata_pbmc3k_processed,
66 | anndata_pbmc68k_reduced,
67 | anndata_suo22_Visium10X,
68 | df_iris,
69 | df_iris_in_meter,
70 | df_iris_in_meter_study1,
71 | df_iris_in_meter_study2,
72 | dict_cellxgene_uns,
73 | dir_iris_images,
74 | dir_scrnaseq_cellranger,
75 | file_bam,
76 | file_fastq,
77 | file_fcs,
78 | file_fcs_alpert19,
79 | file_jpg_paradisi05,
80 | file_mini_csv,
81 | file_tiff_suo22,
82 | file_tsv_rnaseq_nfcore_salmon_merged_gene_counts,
83 | mudata_papalexi21_subset,
84 | schmidt22_crispra_gws_IFNG,
85 | schmidt22_perturbseq,
86 | spatialdata_blobs,
87 | )
88 | from ._fake import fake_bio_notebook_titles
89 | from ._small import (
90 | anndata_with_obs,
91 | small_dataset3_cellxgene,
92 | )
93 |
94 | small_dataset1 = mini_immuno.get_dataset1 # backward compat
95 | small_dataset2 = mini_immuno.get_dataset2 # backward compat
96 |
--------------------------------------------------------------------------------
/lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.2 on 2025-05-06 20:34
2 |
3 | import django.db.models.deletion
4 | from django.db import migrations
5 |
6 | import lamindb.base.fields
7 |
8 |
9 | class Migration(migrations.Migration):
10 | dependencies = [
11 | ("lamindb", "0091_alter_featurevalue_options_alter_space_options_and_more"),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name="artifactfeaturevalue",
17 | name="artifact",
18 | field=lamindb.base.fields.ForeignKey(
19 | blank=True,
20 | on_delete=django.db.models.deletion.CASCADE,
21 | related_name="links_featurevalue",
22 | to="lamindb.artifact",
23 | ),
24 | ),
25 | migrations.AlterField(
26 | model_name="artifactfeaturevalue",
27 | name="featurevalue",
28 | field=lamindb.base.fields.ForeignKey(
29 | blank=True,
30 | on_delete=django.db.models.deletion.PROTECT,
31 | related_name="links_artifact",
32 | to="lamindb.featurevalue",
33 | ),
34 | ),
35 | migrations.AlterField(
36 | model_name="artifactparamvalue",
37 | name="artifact",
38 | field=lamindb.base.fields.ForeignKey(
39 | blank=True,
40 | on_delete=django.db.models.deletion.CASCADE,
41 | related_name="links_paramvalue",
42 | to="lamindb.artifact",
43 | ),
44 | ),
45 | migrations.AlterField(
46 | model_name="artifactparamvalue",
47 | name="paramvalue",
48 | field=lamindb.base.fields.ForeignKey(
49 | blank=True,
50 | on_delete=django.db.models.deletion.PROTECT,
51 | related_name="links_artifact",
52 | to="lamindb.paramvalue",
53 | ),
54 | ),
55 | migrations.AlterField(
56 | model_name="runparamvalue",
57 | name="paramvalue",
58 | field=lamindb.base.fields.ForeignKey(
59 | blank=True,
60 | on_delete=django.db.models.deletion.PROTECT,
61 | related_name="links_run",
62 | to="lamindb.paramvalue",
63 | ),
64 | ),
65 | migrations.AlterField(
66 | model_name="runparamvalue",
67 | name="run",
68 | field=lamindb.base.fields.ForeignKey(
69 | blank=True,
70 | on_delete=django.db.models.deletion.CASCADE,
71 | related_name="links_paramvalue",
72 | to="lamindb.run",
73 | ),
74 | ),
75 | ]
76 |
--------------------------------------------------------------------------------
/tests/storage/test_artifact_zarr.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | from pathlib import Path
3 |
4 | import anndata as ad
5 | import lamindb as ln
6 | import numpy as np
7 | import pandas as pd
8 | import pytest
9 | from lamindb.core.storage._zarr import identify_zarr_type
10 | from lamindb_setup.core.upath import (
11 | CloudPath,
12 | )
13 |
14 |
15 | @pytest.fixture(scope="session")
16 | def get_small_adata():
17 | return ad.AnnData(
18 | X=np.array([[1, 2, 3], [4, 5, 6]]),
19 | obs={"feat1": ["A", "B"]},
20 | var=pd.DataFrame(index=["MYC", "TCF7", "GATA1"]),
21 | obsm={"X_pca": np.array([[1, 2], [3, 4]])},
22 | )
23 |
24 |
25 | def test_zarr_upload_cache(get_small_adata):
26 | previous_storage = ln.setup.settings.storage.root_as_str
27 | ln.settings.storage = "s3://lamindb-test/core"
28 |
29 | zarr_path = Path("./test_adata.zarr")
30 | get_small_adata.write_zarr(zarr_path)
31 |
32 | artifact = ln.Artifact(zarr_path, key="test_adata.zarr")
33 | assert artifact._is_saved_to_storage_location is None
34 | assert artifact.otype == "AnnData"
35 | assert artifact.n_files >= 1
36 | artifact.save()
37 |
38 | assert ln.Artifact.get(path=artifact.path) == artifact
39 |
40 | assert artifact._is_saved_to_storage_location
41 |
42 | assert isinstance(artifact.path, CloudPath)
43 | assert artifact.path.exists()
44 | assert identify_zarr_type(artifact.path) == "anndata"
45 |
46 | shutil.rmtree(artifact.cache())
47 |
48 | cache_path = artifact._cache_path
49 | assert isinstance(artifact.load(), ad.AnnData)
50 | assert cache_path.is_dir()
51 |
52 | shutil.rmtree(cache_path)
53 | assert not cache_path.exists()
54 | artifact.cache()
55 | assert cache_path.is_dir()
56 |
57 | artifact.delete(permanent=True, storage=True)
58 | shutil.rmtree(zarr_path)
59 |
60 | # test zarr from memory
61 | artifact = ln.Artifact(get_small_adata, key="test_adata.anndata.zarr")
62 | assert artifact._is_saved_to_storage_location is None
63 | assert artifact._local_filepath.is_dir()
64 | assert artifact.otype == "AnnData"
65 | assert artifact.suffix == ".anndata.zarr"
66 | assert artifact.n_files >= 1
67 |
68 | ln.save([artifact]) # use bulk save here for testing
69 | assert artifact._is_saved_to_storage_location
70 | assert isinstance(artifact.path, CloudPath)
71 | assert artifact.path.exists()
72 | cache_path = artifact._cache_path
73 | assert cache_path.is_dir()
74 |
75 | shutil.rmtree(cache_path)
76 | assert not cache_path.exists()
77 |
78 | artifact._memory_rep = None
79 |
80 | assert isinstance(artifact.load(), ad.AnnData)
81 | assert cache_path.is_dir()
82 |
83 | artifact.delete(permanent=True, storage=True)
84 |
85 | ln.settings.storage = previous_storage
86 |
--------------------------------------------------------------------------------
/lamindb/examples/cellxgene/cellxgene_schema_versions.csv:
--------------------------------------------------------------------------------
1 | schema_version,entity,organism,source,version
2 | 4.0.0,CellType,all,cl,2023-08-24
3 | 4.0.0,ExperimentalFactor,all,efo,3.57.0
4 | 4.0.0,Ethnicity,human,hancestro,3.0
5 | 4.0.0,DevelopmentalStage,human,hsapdv,2020-03-10
6 | 4.0.0,DevelopmentalStage,mouse,mmusdv,2020-03-10
7 | 4.0.0,Disease,all,mondo,2023-08-02
8 | 4.0.0,Organism,all,ncbitaxon,2023-06-20
9 | 4.0.0,Phenotype,all,pato,2023-05-18
10 | 4.0.0,Tissue,all,uberon,2023-09-05
11 | 5.0.0,CellType,all,cl,2024-01-04
12 | 5.0.0,ExperimentalFactor,all,efo,3.62.0
13 | 5.0.0,Ethnicity,human,hancestro,3.0
14 | 5.0.0,DevelopmentalStage,human,hsapdv,2020-03-10
15 | 5.0.0,DevelopmentalStage,mouse,mmusdv,2020-03-10
16 | 5.0.0,Disease,all,mondo,2024-01-03
17 | 5.0.0,Organism,all,ncbitaxon,2023-06-20
18 | 5.0.0,Phenotype,all,pato,2023-05-18
19 | 5.0.0,Tissue,all,uberon,2024-01-18
20 | 5.0.0,Gene,human,ensembl,release-110
21 | 5.0.0,Gene,mouse,ensembl,release-110
22 | 5.1.0,CellType,all,cl,2024-04-05
23 | 5.1.0,ExperimentalFactor,all,efo,3.65.0
24 | 5.1.0,Ethnicity,human,hancestro,3.0
25 | 5.1.0,DevelopmentalStage,human,hsapdv,2020-03-10
26 | 5.1.0,DevelopmentalStage,mouse,mmusdv,2020-03-10
27 | 5.1.0,Disease,all,mondo,2024-05-08
28 | 5.1.0,Organism,all,ncbitaxon,2023-06-20
29 | 5.1.0,Phenotype,all,pato,2023-05-18
30 | 5.1.0,Tissue,all,uberon,2024-03-22
31 | 5.1.0,Gene,human,ensembl,release-110
32 | 5.1.0,Gene,mouse,ensembl,release-110
33 | 5.2.0,CellType,all,cl,2024-08-16
34 | 5.2.0,ExperimentalFactor,all,efo,3.69.0
35 | 5.2.0,Ethnicity,human,hancestro,3.0
36 | 5.2.0,DevelopmentalStage,human,hsapdv,2024-05-28
37 | 5.2.0,DevelopmentalStage,mouse,mmusdv,2024-05-28
38 | 5.2.0,Disease,all,mondo,2024-08-06
39 | 5.2.0,Organism,all,ncbitaxon,2023-06-20
40 | 5.2.0,Phenotype,all,pato,2023-05-18
41 | 5.2.0,Tissue,all,uberon,2024-08-07
42 | 5.2.0,Gene,human,ensembl,release-110
43 | 5.2.0,Gene,mouse,ensembl,release-110
44 | 5.3.0,CellType,all,cl,2025-02-13
45 | 5.3.0,ExperimentalFactor,all,efo,3.75.0
46 | 5.3.0,Ethnicity,human,hancestro,3.0
47 | 5.3.0,DevelopmentalStage,human,hsapdv,2025-01-23
48 | 5.3.0,DevelopmentalStage,mouse,mmusdv,2025-01-23
49 | 5.3.0,Disease,all,mondo,2025-02-04
50 | 5.3.0,Organism,all,ncbitaxon,2024-11-25
51 | 5.3.0,Phenotype,all,pato,2025-02-01
52 | 5.3.0,Tissue,all,uberon,2025-01-15
53 | 5.3.0,Gene,human,ensembl,release-110
54 | 5.3.0,Gene,mouse,ensembl,release-110
55 | 6.0.0,CellType,all,cl,2025-04-10
56 | 6.0.0,ExperimentalFactor,all,efo,3.78.0
57 | 6.0.0,Ethnicity,human,hancestro,3.0
58 | 6.0.0,DevelopmentalStage,human,hsapdv,2025-01-23
59 | 6.0.0,DevelopmentalStage,mouse,mmusdv,2025-01-23
60 | 6.0.0,Disease,all,mondo,2025-05-06
61 | 6.0.0,Organism,all,ncbitaxon,2025-03-13
62 | 6.0.0,Phenotype,all,pato,2025-05-14
63 | 6.0.0,Tissue,all,uberon,2025-05-28
64 | 6.0.0,Gene,human,ensembl,release-110
65 | 6.0.0,Gene,mouse,ensembl,release-110
66 |
--------------------------------------------------------------------------------
/lamindb/migrations/0139_alter_reference_text.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.2.7 on 2025-10-29 15:16
2 |
3 | from django.db import migrations, models
4 |
5 | import lamindb.base.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 | dependencies = [
10 | ("lamindb", "0138_remove_record_linked_users_user_linked_in_records"),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name="reference",
16 | name="text",
17 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
18 | ),
19 | migrations.RemoveField(
20 | model_name="artifact",
21 | name="ulabels",
22 | ),
23 | migrations.RemoveField(
24 | model_name="artifact",
25 | name="users",
26 | ),
27 | migrations.AddField(
28 | model_name="ulabel",
29 | name="artifacts",
30 | field=models.ManyToManyField(
31 | related_name="ulabels",
32 | through="lamindb.ArtifactULabel",
33 | to="lamindb.artifact",
34 | ),
35 | ),
36 | migrations.AddField(
37 | model_name="user",
38 | name="artifacts",
39 | field=models.ManyToManyField(
40 | related_name="users",
41 | through="lamindb.ArtifactUser",
42 | through_fields=("user", "artifact"),
43 | to="lamindb.artifact",
44 | ),
45 | ),
46 | migrations.RemoveField(
47 | model_name="record",
48 | name="linked_artifacts",
49 | ),
50 | migrations.RemoveField(
51 | model_name="record",
52 | name="linked_runs",
53 | ),
54 | migrations.RemoveField(
55 | model_name="record",
56 | name="linked_ulabels",
57 | ),
58 | migrations.AddField(
59 | model_name="artifact",
60 | name="linked_in_records",
61 | field=models.ManyToManyField(
62 | related_name="linked_artifacts",
63 | through="lamindb.RecordArtifact",
64 | to="lamindb.record",
65 | ),
66 | ),
67 | migrations.AddField(
68 | model_name="run",
69 | name="linked_in_records",
70 | field=models.ManyToManyField(
71 | related_name="linked_runs",
72 | through="lamindb.RecordRun",
73 | to="lamindb.record",
74 | ),
75 | ),
76 | migrations.AddField(
77 | model_name="ulabel",
78 | name="linked_in_records",
79 | field=models.ManyToManyField(
80 | related_name="linked_ulabels",
81 | through="lamindb.RecordULabel",
82 | to="lamindb.record",
83 | ),
84 | ),
85 | ]
86 |
--------------------------------------------------------------------------------
/tests/core/test_querydb.py:
--------------------------------------------------------------------------------
1 | import lamindb as ln
2 | import pytest
3 |
4 |
5 | def test_DB_multiple_instances():
6 | """Accessing multiple instances simultaneously must work."""
7 | cxg_db = ln.DB("laminlabs/cellxgene")
8 | lamindata_db = ln.DB("laminlabs/lamindata")
9 | qs1 = cxg_db.Artifact.filter(suffix=".h5ad")
10 | qs2 = lamindata_db.Artifact.filter(suffix=".zarr")
11 | assert qs1._db != qs2._db
12 |
13 |
14 | def test_DB_bionty():
15 | """Querying a record from bionty must work."""
16 | cxg_db = ln.DB("laminlabs/cellxgene")
17 | assert len(cxg_db.bionty.Gene.filter(symbol__startswith="TP53")) > 0
18 |
19 |
20 | def test_DB_missing_module():
21 | """Attempting to access an attribute that comes from a missing module must error."""
22 | site_assets_db = ln.DB("laminlabs/lamin-site-assets") # instance without bionty
23 |
24 | with pytest.raises(AttributeError) as e:
25 | site_assets_db.bionty.Gene.first()
26 |
27 | assert (
28 | "Schema 'bionty' not available in instance 'laminlabs/lamin-site-assets'."
29 | in str(e.value)
30 | )
31 |
32 |
33 | def test_DB_instantiate_class():
34 | """Attempting to instantiate a class must error."""
35 | cxg_db = ln.DB("laminlabs/cellxgene")
36 | with pytest.raises(TypeError) as e:
37 | cxg_db.Artifact()
38 | assert (
39 | "Cannot instantiate Artifact from DB. Use Artifact.filter(), Artifact.get(), etc. to query records."
40 | in str(e.value)
41 | )
42 |
43 |
44 | @pytest.mark.parametrize(
45 | "attr,expected_msg",
46 | [
47 | ("artifacts", "Registry 'artifacts' not found"),
48 | ("foo", "Registry 'foo' not found"),
49 | ("celltype", "Registry 'celltype' not found"),
50 | ],
51 | )
52 | def test_DB_rejects_invalid_attributes(attr, expected_msg):
53 | """Accessing invalid attributes must fail."""
54 | cxg_db = ln.DB("laminlabs/cellxgene")
55 | with pytest.raises(AttributeError) as e:
56 | getattr(cxg_db, attr)
57 | assert expected_msg in str(e.value)
58 |
59 |
60 | def test_DB_cache():
61 | """Subsequent accesses must return cached wrapper."""
62 | cxg_db = ln.DB("laminlabs/cellxgene")
63 | artifact1 = cxg_db.Artifact
64 | artifact2 = cxg_db.Artifact
65 | assert artifact1 is artifact2
66 |
67 |
68 | def test_queryset_caching():
69 | """Calling `.filter()` multiple times should return different results."""
70 | cxg_db = ln.DB("laminlabs/cellxgene")
71 | res_1 = cxg_db.Artifact.filter().first()
72 | res_2 = cxg_db.Artifact.filter().last()
73 |
74 | assert res_1 != res_2
75 |
76 |
77 | def test_DB_dir():
78 | """__dir__ must return discovered registries."""
79 | cxg = ln.DB("laminlabs/cellxgene")
80 | dir_result = dir(cxg)
81 | assert "Artifact" in dir_result
82 | assert "Collection" in dir_result
83 | assert "Gene" not in dir_result
84 | assert "bionty" in dir_result
85 |
--------------------------------------------------------------------------------
/tests/core/notebooks/basic-r-notebook.Rmd.cleaned.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | library(laminr)
13 |
14 | db <- connect()
15 |
16 |
17 |
18 | → connected lamindb: laminlabs/lamindata
19 |
20 |
21 |
22 | db$track("lOScuxDTDE0q0000")
23 |
24 |
25 |
26 | → loaded Transform('lOScuxDT'), started Run('GWpaTtUg') at 2024-12-01 17:49:18 UTC
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | db$finish()
35 |
36 |
37 |
38 | MoreOUTPUT
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/lamindb/migrations/0125_artifact_is_locked_collection_is_locked_and_more.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.1.12 on 2025-09-29 00:46
2 |
3 | from django.db import migrations
4 |
5 | import lamindb.base.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 | dependencies = [
10 | ("lamindb", "0124_page_artifact_page_collection_page_feature_page_and_more"),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name="artifact",
16 | name="is_locked",
17 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
18 | ),
19 | migrations.AddField(
20 | model_name="collection",
21 | name="is_locked",
22 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
23 | ),
24 | migrations.AddField(
25 | model_name="feature",
26 | name="is_locked",
27 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
28 | ),
29 | migrations.AddField(
30 | model_name="featurevalue",
31 | name="is_locked",
32 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
33 | ),
34 | migrations.AddField(
35 | model_name="project",
36 | name="is_locked",
37 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
38 | ),
39 | migrations.AddField(
40 | model_name="record",
41 | name="is_locked",
42 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
43 | ),
44 | migrations.AddField(
45 | model_name="recordrecord",
46 | name="is_locked",
47 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
48 | ),
49 | migrations.AddField(
50 | model_name="reference",
51 | name="is_locked",
52 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
53 | ),
54 | migrations.AddField(
55 | model_name="run",
56 | name="is_locked",
57 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
58 | ),
59 | migrations.AddField(
60 | model_name="schema",
61 | name="is_locked",
62 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
63 | ),
64 | migrations.AddField(
65 | model_name="storage",
66 | name="is_locked",
67 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
68 | ),
69 | migrations.AddField(
70 | model_name="transform",
71 | name="is_locked",
72 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
73 | ),
74 | migrations.AddField(
75 | model_name="ulabel",
76 | name="is_locked",
77 | field=lamindb.base.fields.BooleanField(blank=True, default=False),
78 | ),
79 | ]
80 |
--------------------------------------------------------------------------------
/tests/core/notebooks/basic-r-notebook.Rmd.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | My exemplary R analysis
5 | My exemplary R analysis
6 |
7 |
8 |
9 |
10 |
11 |
12 | library(laminr)
13 |
14 | db <- connect()
15 |
16 |
17 |
18 | → connected lamindb: laminlabs/lamindata
19 |
20 |
21 |
22 | db$track("lOScuxDTDE0q0000")
23 |
24 |
25 |
26 | → loaded Transform('lOScuxDT'), started Run('GWpaTtUg') at 2024-12-01 17:49:18 UTC
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | db$finish()
35 |
36 |
37 |
38 | MoreOUTPUT ! please hit SHORTCUT to save the notebook in your editor and re-run finish()
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/tests/storage/conftest.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | from pathlib import Path
3 | from subprocess import DEVNULL, run
4 | from time import perf_counter
5 |
6 | import lamindb as ln
7 | import lamindb_setup as ln_setup
8 | import pytest
9 | from lamin_utils import logger
10 | from laminci.db import setup_local_test_postgres
11 |
12 |
13 | def create_test_instance(pgurl: str):
14 | ln.setup.init(
15 | storage="./default_storage_unit_storage",
16 | modules="bionty",
17 | name="lamindb-unit-tests-storage",
18 | db=pgurl,
19 | )
20 | ln.setup.register() # temporarily
21 | ln.settings.creation.artifact_silence_missing_run_warning = True
22 | ln.settings.track_run_inputs = False
23 | ln.Storage("s3://lamindb-ci/test-data").save()
24 | ln.Storage("s3://lamindb-test/core").save()
25 | ln.Storage("s3://lamindb-test/storage").save()
26 |
27 |
28 | def pytest_sessionstart():
29 | t_execute_start = perf_counter()
30 |
31 | ln_setup._TESTING = True
32 | try:
33 | pgurl = setup_local_test_postgres()
34 | except RuntimeError:
35 | run("docker stop pgtest && docker rm pgtest", shell=True, stdout=DEVNULL) # noqa: S602
36 | pgurl = setup_local_test_postgres()
37 | try:
38 | create_test_instance(pgurl)
39 | except Exception as e:
40 | print("failed to create test instance:", e)
41 | print("deleting the instance")
42 | delete_test_instance()
43 | # below currently fails because cannot create two instances in the same session
44 | # create_test_instance(pgurl)
45 | print("now rerun")
46 | quit()
47 | total_time_elapsed = perf_counter() - t_execute_start
48 | print(f"time to setup the instance: {total_time_elapsed:.1f}s")
49 | assert ln.Storage.filter(root="s3://lamindb-ci/test-data").one_or_none() is not None
50 |
51 |
52 | def delete_test_instance():
53 | logger.set_verbosity(1)
54 | if Path("./default_storage_unit_storage").exists():
55 | shutil.rmtree("./default_storage_unit_storage")
56 | # handle below better in the future
57 | for path in (
58 | "s3://lamindb-test/storage/.lamindb",
59 | "s3://lamindb-test/core/.lamindb",
60 | "s3://lamindb-ci/lamindb-unit-tests-cloud/.lamindb",
61 | "s3://lamindb-ci/test-settings-switch-storage/.lamindb",
62 | ):
63 | upath = ln.UPath(path)
64 | if upath.exists():
65 | upath.rmdir()
66 | ln.setup.delete("lamindb-unit-tests-storage", force=True)
67 |
68 |
69 | def pytest_sessionfinish(session: pytest.Session):
70 | delete_test_instance()
71 | run("docker stop pgtest && docker rm pgtest", shell=True, stdout=DEVNULL) # noqa: S602
72 |
73 |
74 | @pytest.fixture
75 | def ccaplog(caplog):
76 | """Add caplog handler to our custom logger at session start."""
77 | from lamin_utils._logger import logger
78 |
79 | # Add caplog's handler to our custom logger
80 | logger.addHandler(caplog.handler)
81 |
82 | yield caplog
83 |
84 | # Clean up at the end of the session
85 | logger.removeHandler(caplog.handler)
86 |
--------------------------------------------------------------------------------
/lamindb/integrations/lightning.py:
--------------------------------------------------------------------------------
1 | """PyTorch Lightning.
2 |
3 | .. autoclass:: Callback
4 | """
5 |
6 | from pathlib import Path
7 | from typing import Any
8 |
9 | import lightning as pl
10 | from lightning.pytorch import LightningModule, Trainer
11 |
12 | import lamindb as ln
13 |
14 |
15 | class Callback(pl.Callback):
16 | """Saves PyTorch Lightning model checkpoints to the LaminDB instance after each training epoch.
17 |
18 | Creates version families of artifacts for given `key` (relative file path).
19 |
20 | See also: :doc:`docs:mlflow` & :doc:`docs:wandb`.
21 |
22 | Args:
23 | path: A local path to the checkpoint.
24 | key: The `key` for the checkpoint artifact.
25 | features: Features to annotate the checkpoint.
26 |
27 | Examples:
28 |
29 | Create a callback that creates artifacts for checkpoints and annotates them by the MLflow run ID::
30 |
31 | import lightning as pl
32 | from lamindb.integrations import lightning as ll
33 |
34 | lamindb_callback = ll.Callback(
35 | path=checkpoint_filename, key=artifact_key, features={"mlflow_run_id": mlflow_run.info.run_id}
36 | )
37 | trainer = pl.Trainer(callbacks=[lamindb_callback])
38 | """
39 |
40 | def __init__(
41 | self,
42 | path: str | Path,
43 | key: str,
44 | features: dict[str, Any] | None = None,
45 | ):
46 | self.path = Path(path)
47 | self.key = key
48 | self.features = features or {}
49 |
50 | def on_train_start(self, trainer: Trainer, pl_module: LightningModule) -> None:
51 | """Validates that features exist for all specified params."""
52 | missing = [
53 | feature
54 | for feature in self.features.keys()
55 | if ln.Feature.filter(name=feature).one_or_none() is None
56 | ]
57 | if missing:
58 | s = "s" if len(missing) > 1 else ""
59 | raise ValueError(
60 | f"Feature{s} {', '.join(missing)} missing. Create {'them' if len(missing) > 1 else 'it'} first."
61 | )
62 |
63 | def on_train_epoch_end(self, trainer: Trainer, pl_module: LightningModule) -> None:
64 | """Saves model checkpoint artifacts at the end of each epoch and optionally annotates them."""
65 | trainer.save_checkpoint(self.path)
66 | af = ln.Artifact(self.path, key=self.key, kind="model").save()
67 |
68 | feature_values = dict(self.features)
69 |
70 | for name in self.features.keys():
71 | if hasattr(trainer, name):
72 | feature_values[name] = getattr(trainer, name)
73 | elif name in trainer.callback_metrics:
74 | metric_value = trainer.callback_metrics[name]
75 | feature_values[name] = (
76 | metric_value.item()
77 | if hasattr(metric_value, "item")
78 | else float(metric_value)
79 | )
80 |
81 | if feature_values:
82 | af.features.add_values(feature_values)
83 |
84 | af.save()
85 |
86 |
87 | __all__ = ["Callback"]
88 |
--------------------------------------------------------------------------------
/lamindb/migrations/0083_alter_feature_is_type_alter_flextable_is_type_and_more.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.2 on 2025-01-25 13:29
2 |
3 | from django.db import migrations
4 |
5 | import lamindb.base.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 | dependencies = [
10 | ("lamindb", "0082_alter_feature_dtype"),
11 | ]
12 |
13 | operations = [
14 | migrations.RunSQL(
15 | sql="""
16 | UPDATE lamindb_feature
17 | SET is_type = FALSE
18 | WHERE is_type IS NULL;
19 |
20 | UPDATE lamindb_flextable
21 | SET is_type = FALSE
22 | WHERE is_type IS NULL;
23 |
24 | UPDATE lamindb_param
25 | SET is_type = FALSE
26 | WHERE is_type IS NULL;
27 |
28 | UPDATE lamindb_project
29 | SET is_type = FALSE
30 | WHERE is_type IS NULL;
31 |
32 | UPDATE lamindb_reference
33 | SET is_type = FALSE
34 | WHERE is_type IS NULL;
35 |
36 | UPDATE lamindb_schema
37 | SET is_type = FALSE
38 | WHERE is_type IS NULL;
39 |
40 | UPDATE lamindb_ulabel
41 | SET is_type = FALSE
42 | WHERE is_type IS NULL;
43 | """
44 | ),
45 | migrations.AlterField(
46 | model_name="feature",
47 | name="is_type",
48 | field=lamindb.base.fields.BooleanField(
49 | blank=True, db_index=True, default=False
50 | ),
51 | ),
52 | migrations.AlterField(
53 | model_name="flextable",
54 | name="is_type",
55 | field=lamindb.base.fields.BooleanField(
56 | blank=True, db_index=True, default=False
57 | ),
58 | ),
59 | migrations.AlterField(
60 | model_name="param",
61 | name="is_type",
62 | field=lamindb.base.fields.BooleanField(
63 | blank=True, db_index=True, default=False
64 | ),
65 | ),
66 | migrations.AlterField(
67 | model_name="project",
68 | name="is_type",
69 | field=lamindb.base.fields.BooleanField(
70 | blank=True, db_index=True, default=False
71 | ),
72 | ),
73 | migrations.AlterField(
74 | model_name="reference",
75 | name="is_type",
76 | field=lamindb.base.fields.BooleanField(
77 | blank=True, db_index=True, default=False
78 | ),
79 | ),
80 | migrations.AlterField(
81 | model_name="schema",
82 | name="is_type",
83 | field=lamindb.base.fields.BooleanField(
84 | blank=True, db_index=True, default=False
85 | ),
86 | ),
87 | migrations.AlterField(
88 | model_name="ulabel",
89 | name="is_type",
90 | field=lamindb.base.fields.BooleanField(
91 | blank=True, db_index=True, default=False
92 | ),
93 | ),
94 | ]
95 |
--------------------------------------------------------------------------------
/lamindb/migrations/0123_alter_artifact_description_alter_branch_description_and_more.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.1.12 on 2025-09-28 21:39
2 |
3 | from django.db import migrations
4 |
5 | import lamindb.base.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 | dependencies = [
10 | ("lamindb", "0122_remove_personproject_person_and_more"),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name="artifact",
16 | name="description",
17 | field=lamindb.base.fields.TextField(
18 | blank=True, db_index=True, default=None, null=True
19 | ),
20 | ),
21 | migrations.AlterField(
22 | model_name="branch",
23 | name="description",
24 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
25 | ),
26 | migrations.AlterField(
27 | model_name="collection",
28 | name="description",
29 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
30 | ),
31 | migrations.AlterField(
32 | model_name="feature",
33 | name="description",
34 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
35 | ),
36 | migrations.AlterField(
37 | model_name="record",
38 | name="description",
39 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
40 | ),
41 | migrations.AlterField(
42 | model_name="schema",
43 | name="description",
44 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
45 | ),
46 | migrations.AlterField(
47 | model_name="space",
48 | name="description",
49 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
50 | ),
51 | migrations.AlterField(
52 | model_name="storage",
53 | name="description",
54 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
55 | ),
56 | migrations.AlterField(
57 | model_name="transform",
58 | name="description",
59 | field=lamindb.base.fields.TextField(
60 | blank=True, db_index=True, default=None, null=True
61 | ),
62 | ),
63 | migrations.AlterField(
64 | model_name="ulabel",
65 | name="description",
66 | field=lamindb.base.fields.TextField(blank=True, default=None, null=True),
67 | ),
68 | migrations.AlterField(
69 | model_name="artifact",
70 | name="key",
71 | field=lamindb.base.fields.CharField(
72 | blank=True, db_index=True, default=None, max_length=1024, null=True
73 | ),
74 | ),
75 | migrations.AlterField(
76 | model_name="transform",
77 | name="key",
78 | field=lamindb.base.fields.CharField(
79 | blank=True, db_index=True, default=None, max_length=1024, null=True
80 | ),
81 | ),
82 | ]
83 |
--------------------------------------------------------------------------------
/tests/curators/test_curate_from_croissant.py:
--------------------------------------------------------------------------------
1 | import shutil
2 |
3 | import lamindb as ln
4 | import pytest
5 |
6 |
7 | @pytest.mark.parametrize("filepath_prefix", [None, "test-curators-db/"])
8 | def test_curate_artifact_from_croissant(filepath_prefix: str | None):
9 | croissant_path, dataset1_path = ln.examples.croissant.mini_immuno(
10 | n_files=1, filepath_prefix=filepath_prefix
11 | )
12 | artifact1 = ln.integrations.curate_from_croissant(croissant_path)
13 | assert (
14 | artifact1.description
15 | == "Mini immuno dataset - A few samples from the immunology dataset"
16 | )
17 | assert artifact1.key == "mini_immuno.anndata.zarr"
18 | assert artifact1.version == "1.0"
19 | assert (
20 | artifact1._key_is_virtual
21 | if filepath_prefix is None
22 | else not artifact1._key_is_virtual
23 | )
24 | license_label = artifact1.ulabels.get(
25 | name="https://creativecommons.org/licenses/by/4.0/"
26 | )
27 | project_label = artifact1.projects.get(name="Mini Immuno Project")
28 |
29 | # now mutate the dataset and create a new version
30 | croissant_path, dataset1_path = ln.examples.croissant.mini_immuno(
31 | n_files=1, filepath_prefix=filepath_prefix, strip_version=True
32 | )
33 | dummy_file_path = dataset1_path / "dummy_file.txt"
34 | dummy_file_path.write_text("dummy file")
35 |
36 | artifact2 = ln.integrations.curate_from_croissant(croissant_path)
37 | assert artifact2.description == artifact1.description
38 | assert artifact2.key == artifact1.key
39 | assert artifact2.version is None
40 | assert artifact2.stem_uid == artifact1.stem_uid
41 | assert artifact2.uid != artifact1.uid
42 | assert (
43 | artifact2._key_is_virtual
44 | if filepath_prefix is None
45 | else not artifact1._key_is_virtual
46 | )
47 | license_label = artifact2.ulabels.get(
48 | name="https://creativecommons.org/licenses/by/4.0/"
49 | )
50 | project_label = artifact2.projects.get(name="Mini Immuno Project")
51 |
52 | shutil.rmtree(dataset1_path)
53 | croissant_path.unlink()
54 | artifact1.delete(permanent=True, storage=True) # because of real storage key
55 | project_label.delete(permanent=True)
56 | license_label.delete(permanent=True)
57 |
58 |
59 | def test_curate_collection_from_croissant():
60 | croissant_path, dataset1_path, dataset2_path = ln.examples.croissant.mini_immuno(
61 | n_files=2
62 | )
63 | collection = ln.integrations.curate_from_croissant(croissant_path)
64 | croissant_path.unlink()
65 | shutil.rmtree(dataset1_path)
66 | dataset2_path.unlink()
67 | artifact1 = collection.artifacts.get(key="mini_immuno.anndata.zarr")
68 | artifact2 = collection.artifacts.get(key="mini.csv")
69 | license_label = collection.ulabels.get(
70 | name="https://creativecommons.org/licenses/by/4.0/"
71 | )
72 | project_label = collection.projects.get(name="Mini Immuno Project")
73 |
74 | collection.delete(permanent=True)
75 | artifact1.delete(permanent=True)
76 | artifact2.delete(permanent=True)
77 | project_label.delete(permanent=True)
78 | license_label.delete(permanent=True)
79 |
--------------------------------------------------------------------------------
/lamindb/migrations/0086_various.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.2 on 2025-02-06 07:10
2 |
3 | from django.db import migrations, models
4 |
5 | import lamindb.base.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 | dependencies = [
10 | ("lamindb", "0085_alter_feature_is_type_alter_flextable_is_type_and_more"),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name="transform",
16 | name="hash",
17 | field=lamindb.base.fields.CharField(
18 | blank=True,
19 | db_index=True,
20 | default=None,
21 | max_length=22,
22 | null=True,
23 | unique=True,
24 | ),
25 | ),
26 | migrations.AlterField(
27 | model_name="artifact",
28 | name="hash",
29 | field=lamindb.base.fields.CharField(
30 | blank=True,
31 | db_index=True,
32 | default=None,
33 | max_length=22,
34 | null=True,
35 | unique=True,
36 | ),
37 | ),
38 | migrations.AlterField(
39 | model_name="collection",
40 | name="hash",
41 | field=lamindb.base.fields.CharField(
42 | blank=True,
43 | db_index=True,
44 | default=None,
45 | max_length=22,
46 | null=True,
47 | unique=True,
48 | ),
49 | ),
50 | migrations.CreateModel(
51 | name="Migration",
52 | fields=[
53 | (
54 | "id",
55 | models.BigAutoField(
56 | auto_created=True,
57 | primary_key=True,
58 | serialize=False,
59 | verbose_name="ID",
60 | ),
61 | ),
62 | (
63 | "app",
64 | lamindb.base.fields.CharField(
65 | blank=True, default=None, max_length=255
66 | ),
67 | ),
68 | (
69 | "name",
70 | lamindb.base.fields.CharField(
71 | blank=True, default=None, max_length=255
72 | ),
73 | ),
74 | ("applied", lamindb.base.fields.DateTimeField(blank=True)),
75 | ],
76 | options={
77 | "db_table": "django_migrations",
78 | "managed": False,
79 | },
80 | ),
81 | migrations.AlterField(
82 | model_name="param",
83 | name="dtype",
84 | field=lamindb.base.fields.CharField(
85 | blank=True, db_index=True, default=None, max_length=64, null=True
86 | ),
87 | ),
88 | migrations.AlterField(
89 | model_name="param",
90 | name="dtype",
91 | field=lamindb.base.fields.CharField(
92 | blank=True, db_index=True, default=None, max_length=255, null=True
93 | ),
94 | ),
95 | ]
96 |
--------------------------------------------------------------------------------
/tests/core/test_rename_features_labels.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import os
3 |
4 | import lamindb as ln
5 | import pandas as pd
6 | import pytest
7 |
8 |
9 | def test_rename_feature(ccaplog):
10 | df = pd.DataFrame({"old_name": [1, 2]})
11 | ln.Feature(name="old_name", dtype=int).save()
12 | artifact = ln.Artifact.from_dataframe(
13 | df, key="test.parquet", schema="valid_features"
14 | ).save()
15 | feature = ln.Feature.get(name="old_name")
16 |
17 | # First rename
18 | feature.name = "new_name"
19 | feature.save()
20 | now1 = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
21 | assert (
22 | "by renaming feature from 'old_name' to 'new_name' 1 artifact no longer matches the feature name in storage:"
23 | in ccaplog.text
24 | )
25 | if os.getenv("LAMINDB_TEST_DB_VENDOR") != "sqlite":
26 | feature.refresh_from_db()
27 | assert feature.synonyms == "old_name"
28 | assert feature._aux["renamed"] == {
29 | now1.isoformat().replace("+00:00", "Z"): "old_name"
30 | }
31 |
32 | # Second rename
33 | feature.name = "newer_name"
34 | feature.save()
35 | now2 = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
36 | assert (
37 | "by renaming feature from 'new_name' to 'newer_name' 1 artifact no longer matches the feature name in storage:"
38 | in ccaplog.text
39 | )
40 | if os.getenv("LAMINDB_TEST_DB_VENDOR") != "sqlite":
41 | feature.refresh_from_db()
42 | assert feature.synonyms == "old_name|new_name"
43 | assert feature._aux["renamed"] == {
44 | now1.isoformat().replace("+00:00", "Z"): "old_name",
45 | now2.isoformat().replace("+00:00", "Z"): "new_name",
46 | }
47 |
48 | schema = artifact.feature_sets.first()
49 | artifact.delete(permanent=True)
50 | schema.delete(permanent=True)
51 | feature.delete(permanent=True)
52 |
53 |
54 | @pytest.mark.parametrize("model_class", [ln.ULabel, ln.Record])
55 | def test_rename_label(model_class, ccaplog):
56 | df = pd.DataFrame(
57 | {
58 | "feature1": pd.Categorical(["label1", "label2"]),
59 | "feature2": pd.Categorical(["label2", "label2"]),
60 | }
61 | )
62 |
63 | label1 = model_class(name="label1").save()
64 | label2 = model_class(name="label2").save()
65 | feature1 = ln.Feature(name="feature1", dtype=model_class).save()
66 | feature2 = ln.Feature(name="feature2", dtype=model_class).save()
67 | artifact = ln.Artifact.from_dataframe(
68 | df, key="test.parquet", schema="valid_features"
69 | ).save()
70 |
71 | label = model_class.get(name="label1")
72 | label.name = "label-renamed"
73 | label.save()
74 |
75 | assert (
76 | "by renaming label from 'label1' to 'label-renamed' 1 artifact no longer matches the label name in storage:"
77 | in ccaplog.text
78 | )
79 |
80 | schema = artifact.feature_sets.first()
81 | artifact.delete(permanent=True)
82 | schema.delete(permanent=True)
83 | feature1.delete(permanent=True)
84 | feature2.delete(permanent=True)
85 | label1.delete(permanent=True)
86 | label2.delete(permanent=True)
87 |
--------------------------------------------------------------------------------
/lamindb/examples/croissant/mini_immuno.anndata.zarr_metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "@context": {
3 | "@vocab": "https://schema.org/",
4 | "cr": "https://mlcommons.org/croissant/",
5 | "ml": "http://ml-schema.org/",
6 | "sc": "https://schema.org/",
7 | "dct": "http://purl.org/dc/terms/",
8 | "data": "https://mlcommons.org/croissant/data/",
9 | "rai": "https://mlcommons.org/croissant/rai/",
10 | "format": "https://mlcommons.org/croissant/format/",
11 | "citeAs": "https://mlcommons.org/croissant/citeAs/",
12 | "conformsTo": "https://mlcommons.org/croissant/conformsTo/",
13 | "@language": "en",
14 | "repeated": "https://mlcommons.org/croissant/repeated/",
15 | "field": "https://mlcommons.org/croissant/field/",
16 | "examples": "https://mlcommons.org/croissant/examples/",
17 | "recordSet": "https://mlcommons.org/croissant/recordSet/",
18 | "fileObject": "https://mlcommons.org/croissant/fileObject/",
19 | "fileSet": "https://mlcommons.org/croissant/fileSet/",
20 | "source": "https://mlcommons.org/croissant/source/",
21 | "references": "https://mlcommons.org/croissant/references/",
22 | "key": "https://mlcommons.org/croissant/key/",
23 | "parentField": "https://mlcommons.org/croissant/parentField/",
24 | "isLiveDataset": "https://mlcommons.org/croissant/isLiveDataset/",
25 | "separator": "https://mlcommons.org/croissant/separator/",
26 | "extract": "https://mlcommons.org/croissant/extract/",
27 | "subField": "https://mlcommons.org/croissant/subField/",
28 | "regex": "https://mlcommons.org/croissant/regex/",
29 | "column": "https://mlcommons.org/croissant/column/",
30 | "path": "https://mlcommons.org/croissant/path/",
31 | "fileProperty": "https://mlcommons.org/croissant/fileProperty/",
32 | "md5": "https://mlcommons.org/croissant/md5/",
33 | "jsonPath": "https://mlcommons.org/croissant/jsonPath/",
34 | "transform": "https://mlcommons.org/croissant/transform/",
35 | "replace": "https://mlcommons.org/croissant/replace/",
36 | "dataType": "https://mlcommons.org/croissant/dataType/",
37 | "includes": "https://mlcommons.org/croissant/includes/",
38 | "excludes": "https://mlcommons.org/croissant/excludes/"
39 | },
40 | "@type": "Dataset",
41 | "name": "Mini immuno dataset",
42 | "description": "A few samples from the immunology dataset",
43 | "url": "https://lamin.ai/laminlabs/lamindata/artifact/tCUkRcaEjTjhtozp0000",
44 | "creator": {
45 | "@type": "Person",
46 | "name": "falexwolf"
47 | },
48 | "dateCreated": "2025-07-16",
49 | "cr:projectName": "Mini Immuno Project",
50 | "datePublished": "2025-07-16",
51 | "version": "1.0",
52 | "license": "https://creativecommons.org/licenses/by/4.0/",
53 | "citation": "Please cite this dataset as: mini immuno (2025)",
54 | "encodingFormat": "zarr",
55 | "distribution": [
56 | {
57 | "@type": "cr:FileSet",
58 | "@id": "mini_immuno.anndata.zarr",
59 | "containedIn": {
60 | "@id": "directory"
61 | },
62 | "encodingFormat": "zarr"
63 | }
64 | ],
65 | "cr:recordSet": [
66 | {
67 | "@type": "cr:RecordSet",
68 | "@id": "#samples",
69 | "name": "samples",
70 | "description": "my sample"
71 | }
72 | ]
73 | }
74 |
--------------------------------------------------------------------------------