lamindb 1.4.0__py3-none-any.whl → 1.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lamindb/__init__.py +52 -36
- lamindb/_finish.py +17 -10
- lamindb/_tracked.py +1 -1
- lamindb/base/__init__.py +3 -1
- lamindb/base/fields.py +40 -22
- lamindb/base/ids.py +1 -94
- lamindb/base/types.py +2 -0
- lamindb/base/uids.py +117 -0
- lamindb/core/_context.py +203 -102
- lamindb/core/_settings.py +38 -25
- lamindb/core/datasets/__init__.py +11 -4
- lamindb/core/datasets/_core.py +5 -5
- lamindb/core/datasets/_small.py +0 -93
- lamindb/core/datasets/mini_immuno.py +172 -0
- lamindb/core/loaders.py +1 -1
- lamindb/core/storage/_backed_access.py +100 -6
- lamindb/core/storage/_polars_lazy_df.py +51 -0
- lamindb/core/storage/_pyarrow_dataset.py +15 -30
- lamindb/core/storage/_tiledbsoma.py +29 -13
- lamindb/core/storage/objects.py +6 -0
- lamindb/core/subsettings/__init__.py +2 -0
- lamindb/core/subsettings/_annotation_settings.py +11 -0
- lamindb/curators/__init__.py +7 -3349
- lamindb/curators/_legacy.py +2056 -0
- lamindb/curators/core.py +1534 -0
- lamindb/errors.py +11 -0
- lamindb/examples/__init__.py +27 -0
- lamindb/examples/schemas/__init__.py +12 -0
- lamindb/examples/schemas/_anndata.py +25 -0
- lamindb/examples/schemas/_simple.py +19 -0
- lamindb/integrations/_vitessce.py +8 -5
- lamindb/migrations/0091_alter_featurevalue_options_alter_space_options_and_more.py +24 -0
- lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py +75 -0
- lamindb/migrations/0093_alter_schemacomponent_unique_together.py +16 -0
- lamindb/models/__init__.py +4 -1
- lamindb/models/_describe.py +21 -4
- lamindb/models/_feature_manager.py +382 -287
- lamindb/models/_label_manager.py +8 -2
- lamindb/models/artifact.py +177 -106
- lamindb/models/artifact_set.py +122 -0
- lamindb/models/collection.py +73 -52
- lamindb/models/core.py +1 -1
- lamindb/models/feature.py +51 -17
- lamindb/models/has_parents.py +69 -14
- lamindb/models/project.py +1 -1
- lamindb/models/query_manager.py +221 -22
- lamindb/models/query_set.py +247 -172
- lamindb/models/record.py +65 -247
- lamindb/models/run.py +4 -4
- lamindb/models/save.py +8 -2
- lamindb/models/schema.py +456 -184
- lamindb/models/transform.py +2 -2
- lamindb/models/ulabel.py +8 -5
- {lamindb-1.4.0.dist-info → lamindb-1.5.1.dist-info}/METADATA +6 -6
- {lamindb-1.4.0.dist-info → lamindb-1.5.1.dist-info}/RECORD +57 -43
- {lamindb-1.4.0.dist-info → lamindb-1.5.1.dist-info}/LICENSE +0 -0
- {lamindb-1.4.0.dist-info → lamindb-1.5.1.dist-info}/WHEEL +0 -0
lamindb/errors.py
CHANGED
@@ -94,3 +94,14 @@ class UpdateContext(SystemExit):
|
|
94
94
|
"""Transform settings require update."""
|
95
95
|
|
96
96
|
pass
|
97
|
+
|
98
|
+
|
99
|
+
# -------------------------------------------------------------------------------------
|
100
|
+
# record
|
101
|
+
# -------------------------------------------------------------------------------------
|
102
|
+
|
103
|
+
|
104
|
+
class NoWriteAccess(Exception):
|
105
|
+
"""No write access to a space."""
|
106
|
+
|
107
|
+
pass
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"""Examples.
|
2
|
+
|
3
|
+
.. autosummary::
|
4
|
+
:toctree: .
|
5
|
+
|
6
|
+
ingest_mini_immuno_datasets
|
7
|
+
schemas
|
8
|
+
|
9
|
+
"""
|
10
|
+
|
11
|
+
from . import schemas
|
12
|
+
|
13
|
+
|
14
|
+
def ingest_mini_immuno_datasets():
|
15
|
+
"""Ingest mini immuno datasets.
|
16
|
+
|
17
|
+
.. literalinclude:: scripts/ingest_mini_immuno_datasets.py
|
18
|
+
:language: python
|
19
|
+
"""
|
20
|
+
import sys
|
21
|
+
from pathlib import Path
|
22
|
+
|
23
|
+
docs_path = Path(__file__).parent.parent.parent / "docs" / "scripts"
|
24
|
+
if str(docs_path) not in sys.path:
|
25
|
+
sys.path.append(str(docs_path))
|
26
|
+
|
27
|
+
import ingest_mini_immuno_datasets # noqa
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from ... import Schema
|
2
|
+
|
3
|
+
|
4
|
+
def anndata_ensembl_gene_ids_and_valid_features_in_obs() -> Schema:
|
5
|
+
"""Return a schema for an AnnData with Ensembl gene IDs and valid features in obs.
|
6
|
+
|
7
|
+
.. literalinclude:: scripts/define_schema_anndata_ensembl_gene_ids_and_valid_features_in_obs.py
|
8
|
+
:language: python
|
9
|
+
"""
|
10
|
+
import subprocess
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
docs_path = Path(__file__).parent.parent.parent.parent / "docs" / "scripts"
|
14
|
+
subprocess.run(
|
15
|
+
[
|
16
|
+
"python",
|
17
|
+
str(
|
18
|
+
docs_path
|
19
|
+
/ "define_schema_anndata_ensembl_gene_ids_and_valid_features_in_obs.py"
|
20
|
+
),
|
21
|
+
],
|
22
|
+
check=True,
|
23
|
+
)
|
24
|
+
|
25
|
+
return Schema.get(name="anndata_ensembl_gene_ids_and_valid_features_in_obs")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from ... import Schema
|
2
|
+
|
3
|
+
|
4
|
+
def valid_features() -> Schema:
|
5
|
+
"""Return a schema for an AnnData with Ensembl gene IDs and valid features in obs.
|
6
|
+
|
7
|
+
.. literalinclude:: scripts/define_schema_anndata_ensembl_gene_ids_and_valid_features_in_obs.py
|
8
|
+
:language: python
|
9
|
+
"""
|
10
|
+
import subprocess
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
docs_path = Path(__file__).parent.parent.parent.parent / "docs" / "scripts"
|
14
|
+
subprocess.run(
|
15
|
+
["python", str(docs_path / "define_valid_features.py")],
|
16
|
+
check=True,
|
17
|
+
)
|
18
|
+
|
19
|
+
return Schema.get(name="valid_features")
|
@@ -19,7 +19,9 @@ if TYPE_CHECKING:
|
|
19
19
|
# "unit test": https://github.com/laminlabs/lamindb/blob/main/docs/storage/vitessce.ipynb
|
20
20
|
# integration test & context: https://github.com/laminlabs/lamin-spatial/blob/main/docs/vitessce.ipynb
|
21
21
|
def save_vitessce_config(
|
22
|
-
vitessce_config: VitessceConfig,
|
22
|
+
vitessce_config: VitessceConfig,
|
23
|
+
key: str | None = None,
|
24
|
+
description: str | None = None,
|
23
25
|
) -> Artifact:
|
24
26
|
"""Validates and saves a `VitessceConfig` object.
|
25
27
|
|
@@ -30,9 +32,10 @@ def save_vitessce_config(
|
|
30
32
|
|
31
33
|
Args:
|
32
34
|
vitessce_config: A `VitessceConfig` object.
|
33
|
-
|
34
|
-
`
|
35
|
-
|
35
|
+
key: A key for the `VitessceConfig` object. Is used as `key` for a
|
36
|
+
`Collection` in case the `VitessceConfig` object references
|
37
|
+
multiple artifacts.
|
38
|
+
description: A description for the `VitessceConfig` object.
|
36
39
|
|
37
40
|
.. versionchanged:: 0.76.12
|
38
41
|
Now assumes `vitessce-python >= 3.4.0`, which allows passing artifacts within `VitessceConfig`.
|
@@ -77,7 +80,7 @@ def save_vitessce_config(
|
|
77
80
|
with open(config_file_local_path, "w") as file:
|
78
81
|
json.dump(vc_dict, file)
|
79
82
|
vitessce_config_artifact = Artifact(
|
80
|
-
config_file_local_path, description=description, run=run
|
83
|
+
config_file_local_path, key=key, description=description, run=run
|
81
84
|
).save()
|
82
85
|
slug = ln_setup.settings.instance.slug
|
83
86
|
logger.important(
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Generated by Django 5.1.4 on 2025-04-30 09:11
|
2
|
+
|
3
|
+
from django.db import migrations
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("lamindb", "0090_squashed"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.AlterModelOptions(
|
13
|
+
name="featurevalue",
|
14
|
+
options={"base_manager_name": "objects"},
|
15
|
+
),
|
16
|
+
migrations.AlterModelOptions(
|
17
|
+
name="space",
|
18
|
+
options={"base_manager_name": "objects"},
|
19
|
+
),
|
20
|
+
migrations.AlterModelOptions(
|
21
|
+
name="user",
|
22
|
+
options={"base_manager_name": "objects"},
|
23
|
+
),
|
24
|
+
]
|
@@ -0,0 +1,75 @@
|
|
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
|
+
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Generated by Django 5.2 on 2025-05-07 12:16
|
2
|
+
|
3
|
+
from django.db import migrations
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("lamindb", "0092_alter_artifactfeaturevalue_artifact_and_more"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.AlterUniqueTogether(
|
13
|
+
name="schemacomponent",
|
14
|
+
unique_together={("composite", "slot"), ("composite", "slot", "component")},
|
15
|
+
),
|
16
|
+
]
|
lamindb/models/__init__.py
CHANGED
@@ -6,7 +6,9 @@
|
|
6
6
|
BasicRecord
|
7
7
|
Record
|
8
8
|
Registry
|
9
|
+
BasicQuerySet
|
9
10
|
QuerySet
|
11
|
+
ArtifactSet
|
10
12
|
QueryManager
|
11
13
|
RecordList
|
12
14
|
FeatureManager
|
@@ -55,7 +57,8 @@ from .collection import Collection, CollectionArtifact
|
|
55
57
|
from .project import Person, Project, Reference
|
56
58
|
from .flextable import FlexTable, RunData
|
57
59
|
from .query_manager import QueryManager
|
58
|
-
from .query_set import QuerySet, RecordList
|
60
|
+
from .query_set import BasicQuerySet, QuerySet, RecordList
|
61
|
+
from .artifact_set import ArtifactSet
|
59
62
|
from .has_parents import HasParents
|
60
63
|
from datetime import datetime as _datetime
|
61
64
|
|
lamindb/models/_describe.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import datetime
|
4
|
+
import re
|
4
5
|
from typing import TYPE_CHECKING
|
5
6
|
|
6
7
|
from lamin_utils import logger
|
@@ -35,7 +36,9 @@ TYPE_WIDTH = 25
|
|
35
36
|
VALUES_WIDTH = 40
|
36
37
|
|
37
38
|
|
38
|
-
def
|
39
|
+
def format_rich_tree(
|
40
|
+
tree: Tree, fallback: str = "", return_str: bool = False, strip_ansi: bool = True
|
41
|
+
) -> str | None:
|
39
42
|
from rich.console import Console
|
40
43
|
|
41
44
|
# If tree has no children, return fallback
|
@@ -45,6 +48,20 @@ def print_rich_tree(tree: Tree, fallback=str):
|
|
45
48
|
console = Console(force_terminal=True)
|
46
49
|
printed = False
|
47
50
|
|
51
|
+
if return_str:
|
52
|
+
from io import StringIO
|
53
|
+
|
54
|
+
string_io = StringIO()
|
55
|
+
str_console = Console(file=string_io, force_terminal=True)
|
56
|
+
str_console.print(tree)
|
57
|
+
result = string_io.getvalue()
|
58
|
+
if strip_ansi:
|
59
|
+
ansi_escape = re.compile(r"\x1b(?:\[[0-9;]*[a-zA-Z]|\(B)")
|
60
|
+
result = ansi_escape.sub("", result)
|
61
|
+
# rstrip trailing whitespace on every line
|
62
|
+
result = "\n".join(line.rstrip() for line in result.splitlines())
|
63
|
+
return result
|
64
|
+
|
48
65
|
try:
|
49
66
|
if not is_run_from_ipython:
|
50
67
|
from IPython import get_ipython
|
@@ -55,16 +72,16 @@ def print_rich_tree(tree: Tree, fallback=str):
|
|
55
72
|
if isinstance(shell, InteractiveShell):
|
56
73
|
display(tree)
|
57
74
|
printed = True
|
58
|
-
return
|
75
|
+
return None
|
59
76
|
except (NameError, ImportError):
|
60
77
|
pass
|
61
78
|
|
62
|
-
# If not printed through IPython
|
63
79
|
if not printed:
|
64
80
|
# be careful to test this on a terminal
|
65
81
|
console = Console(force_terminal=True)
|
66
82
|
console.print(tree)
|
67
|
-
|
83
|
+
|
84
|
+
return None
|
68
85
|
|
69
86
|
|
70
87
|
def describe_header(self: Artifact | Collection | Run) -> Tree:
|