lamindb 1.11a1__py3-none-any.whl → 1.11.2__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 +1 -1
- lamindb/_finish.py +3 -3
- lamindb/core/_context.py +4 -2
- lamindb/curators/core.py +13 -5
- lamindb/errors.py +6 -0
- lamindb/examples/cellxgene/_cellxgene.py +1 -1
- lamindb/examples/croissant/__init__.py +20 -4
- lamindb/examples/datasets/_core.py +8 -1
- lamindb/examples/datasets/mini_immuno.py +0 -1
- lamindb/examples/fixtures/sheets.py +8 -2
- lamindb/integrations/_croissant.py +34 -11
- lamindb/migrations/0121_recorduser.py +7 -0
- lamindb/models/__init__.py +1 -0
- lamindb/models/_feature_manager.py +78 -18
- lamindb/models/artifact.py +71 -65
- lamindb/models/artifact_set.py +12 -3
- lamindb/models/query_set.py +170 -74
- lamindb/models/record.py +5 -1
- lamindb/models/run.py +2 -27
- lamindb/models/save.py +18 -10
- lamindb/models/sqlrecord.py +47 -33
- lamindb-1.11.2.dist-info/METADATA +180 -0
- {lamindb-1.11a1.dist-info → lamindb-1.11.2.dist-info}/RECORD +25 -25
- lamindb-1.11a1.dist-info/METADATA +0 -144
- {lamindb-1.11a1.dist-info → lamindb-1.11.2.dist-info}/LICENSE +0 -0
- {lamindb-1.11a1.dist-info → lamindb-1.11.2.dist-info}/WHEEL +0 -0
lamindb/models/run.py
CHANGED
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import TYPE_CHECKING, overload
|
4
4
|
|
5
|
-
import numpy as np
|
6
5
|
from django.db import models
|
7
6
|
from django.db.models import (
|
8
7
|
CASCADE,
|
@@ -18,7 +17,6 @@ from lamindb.base.fields import (
|
|
18
17
|
ForeignKey,
|
19
18
|
)
|
20
19
|
from lamindb.base.users import current_user_id
|
21
|
-
from lamindb.errors import InvalidArgument
|
22
20
|
|
23
21
|
from ..base.ids import base62_16
|
24
22
|
from .can_curate import CanCurate
|
@@ -428,31 +426,8 @@ class Run(SQLRecord):
|
|
428
426
|
|
429
427
|
ln.Run.filter(hyperparam_x=100)
|
430
428
|
"""
|
431
|
-
from
|
432
|
-
|
433
|
-
from .query_set import QuerySet
|
434
|
-
|
435
|
-
if expressions:
|
436
|
-
keys_normalized = [key.split("__")[0] for key in expressions]
|
437
|
-
field_or_feature_or_param = keys_normalized[0].split("__")[0]
|
438
|
-
if field_or_feature_or_param in Run.__get_available_fields__():
|
439
|
-
return QuerySet(model=cls).filter(*queries, **expressions)
|
440
|
-
elif all(
|
441
|
-
params_validated := Feature.validate(
|
442
|
-
keys_normalized, field="name", mute=True
|
443
|
-
)
|
444
|
-
):
|
445
|
-
return filter_base(Run, **expressions)
|
446
|
-
else:
|
447
|
-
params = ", ".join(sorted(np.array(keys_normalized)[~params_validated]))
|
448
|
-
message = f"feature names: {params}"
|
449
|
-
fields = ", ".join(sorted(cls.__get_available_fields__()))
|
450
|
-
raise InvalidArgument(
|
451
|
-
f"You can query either by available fields: {fields}\n"
|
452
|
-
f"Or fix invalid {message}"
|
453
|
-
)
|
454
|
-
else:
|
455
|
-
return QuerySet(model=cls).filter(*queries, **expressions)
|
429
|
+
# from Registry metaclass
|
430
|
+
return type(cls).filter(cls, *queries, **expressions)
|
456
431
|
|
457
432
|
|
458
433
|
def delete_run_artifacts(run: Run) -> None:
|
lamindb/models/save.py
CHANGED
@@ -47,11 +47,10 @@ def save(
|
|
47
47
|
|
48
48
|
Args:
|
49
49
|
records: Multiple :class:`~lamindb.models.SQLRecord` objects.
|
50
|
-
ignore_conflicts: If
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
batch_size: Number of records to process in each batch. Defaults to 10000.
|
50
|
+
ignore_conflicts: If `True`, do not error if some records violate a unique or another constraint.
|
51
|
+
However, it won't inplace update the id fields of records.
|
52
|
+
If you need records with ids, you need to query them from the database.
|
53
|
+
batch_size: Number of records to process in each batch.
|
55
54
|
Large batch sizes can improve performance but may lead to memory issues.
|
56
55
|
|
57
56
|
Examples:
|
@@ -130,7 +129,7 @@ def bulk_create(
|
|
130
129
|
Args:
|
131
130
|
records: Iterable of SQLRecord objects to create
|
132
131
|
ignore_conflicts: Whether to ignore conflicts during creation
|
133
|
-
batch_size: Number of records to process in each batch.
|
132
|
+
batch_size: Number of records to process in each batch.
|
134
133
|
"""
|
135
134
|
records_by_orm = defaultdict(list)
|
136
135
|
for record in records:
|
@@ -235,7 +234,15 @@ def check_and_attempt_upload(
|
|
235
234
|
try:
|
236
235
|
copy_or_move_to_cache(artifact, storage_path, cache_path)
|
237
236
|
except Exception as e:
|
238
|
-
|
237
|
+
if not str(e).startswith(
|
238
|
+
"[WinError 32] The process cannot access the file "
|
239
|
+
"because it is being used by another process"
|
240
|
+
):
|
241
|
+
# ignore WinError 32 error, this just means that the file is still open on save
|
242
|
+
# it is saved at this point, so not a big deal if copy or move to cache fails
|
243
|
+
# this mostly happens for run logs
|
244
|
+
# just ignore without a warning
|
245
|
+
logger.warning(f"A problem with cache on saving: {e}")
|
239
246
|
# after successful upload, we should remove the attribute so that another call
|
240
247
|
# call to save won't upload again, the user should call replace() then
|
241
248
|
del artifact._local_filepath
|
@@ -270,7 +277,9 @@ def copy_or_move_to_cache(
|
|
270
277
|
# non-local storage_path further
|
271
278
|
if local_path != cache_path:
|
272
279
|
if cache_path.exists():
|
273
|
-
logger.
|
280
|
+
logger.important_hint(
|
281
|
+
f"replacing the existing cache path {cache_path.as_posix()}"
|
282
|
+
)
|
274
283
|
if cache_path.is_dir():
|
275
284
|
shutil.rmtree(cache_path)
|
276
285
|
else:
|
@@ -332,8 +341,7 @@ def store_artifacts(
|
|
332
341
|
from .artifact import Artifact
|
333
342
|
|
334
343
|
exception: Exception | None = None
|
335
|
-
# because uploads might fail, we need to maintain a new list
|
336
|
-
# of the succeeded uploads
|
344
|
+
# because uploads might fail, we need to maintain a new list of the succeeded uploads
|
337
345
|
stored_artifacts = []
|
338
346
|
|
339
347
|
# upload new local artifacts
|
lamindb/models/sqlrecord.py
CHANGED
@@ -319,6 +319,43 @@ def suggest_records_with_similar_names(
|
|
319
319
|
return None
|
320
320
|
|
321
321
|
|
322
|
+
def delete_record(record: BaseSQLRecord, is_soft: bool = True):
|
323
|
+
def delete():
|
324
|
+
if is_soft:
|
325
|
+
record.branch_id = -1
|
326
|
+
record.save()
|
327
|
+
else:
|
328
|
+
super(BaseSQLRecord, record).delete()
|
329
|
+
|
330
|
+
# deal with versioned records
|
331
|
+
# if _ovewrite_version = True, there is only a single version and
|
332
|
+
# no need to set the new latest version because all versions are deleted
|
333
|
+
# when deleting the latest version
|
334
|
+
if (
|
335
|
+
isinstance(record, IsVersioned)
|
336
|
+
and record.is_latest
|
337
|
+
and not getattr(record, "_overwrite_versions", False)
|
338
|
+
):
|
339
|
+
new_latest = (
|
340
|
+
record.__class__.objects.using(record._state.db)
|
341
|
+
.filter(is_latest=False, uid__startswith=record.stem_uid)
|
342
|
+
.exclude(branch_id=-1) # exclude candidates in the trash
|
343
|
+
.order_by("-created_at")
|
344
|
+
.first()
|
345
|
+
)
|
346
|
+
if new_latest is not None:
|
347
|
+
new_latest.is_latest = True
|
348
|
+
if is_soft:
|
349
|
+
record.is_latest = False
|
350
|
+
with transaction.atomic():
|
351
|
+
new_latest.save()
|
352
|
+
delete()
|
353
|
+
logger.important_hint(f"new latest version is: {new_latest}")
|
354
|
+
return None
|
355
|
+
# deal with all other cases of the nested if condition now
|
356
|
+
delete()
|
357
|
+
|
358
|
+
|
322
359
|
RECORD_REGISTRY_EXAMPLE = """Example::
|
323
360
|
|
324
361
|
from lamindb import SQLRecord, fields
|
@@ -589,7 +626,7 @@ class Registry(ModelBase):
|
|
589
626
|
# this just retrives the full connection string from iresult
|
590
627
|
db = update_db_using_local(iresult, settings_file)
|
591
628
|
cache_using_filepath.write_text(
|
592
|
-
f"{iresult['lnid']}\n{iresult['schema_str']}"
|
629
|
+
f"{iresult['lnid']}\n{iresult['schema_str']}", encoding="utf-8"
|
593
630
|
)
|
594
631
|
# need to set the token if it is a fine_grained_access and the user is jwt (not public)
|
595
632
|
is_fine_grained_access = (
|
@@ -602,7 +639,7 @@ class Registry(ModelBase):
|
|
602
639
|
source_modules = isettings.modules
|
603
640
|
db = isettings.db
|
604
641
|
cache_using_filepath.write_text(
|
605
|
-
f"{isettings.uid}\n{','.join(source_modules)}"
|
642
|
+
f"{isettings.uid}\n{','.join(source_modules)}", encoding="utf-8"
|
606
643
|
)
|
607
644
|
# need to set the token if it is a fine_grained_access and the user is jwt (not public)
|
608
645
|
is_fine_grained_access = (
|
@@ -881,7 +918,7 @@ class BaseSQLRecord(models.Model, metaclass=Registry):
|
|
881
918
|
):
|
882
919
|
raise NoWriteAccess(
|
883
920
|
f"You’re not allowed to write to the space '{self.space.name}'.\n"
|
884
|
-
"Please contact
|
921
|
+
"Please contact administrators of the space if you need write access."
|
885
922
|
) from None
|
886
923
|
else:
|
887
924
|
raise
|
@@ -929,29 +966,7 @@ class BaseSQLRecord(models.Model, metaclass=Registry):
|
|
929
966
|
|
930
967
|
def delete(self) -> None:
|
931
968
|
"""Delete."""
|
932
|
-
|
933
|
-
# _overwrite_versions is set to True for folder artifacts
|
934
|
-
# no need to set the new latest version becase all versions are deleted
|
935
|
-
# when deleting the latest version of a folder artifact
|
936
|
-
if (
|
937
|
-
isinstance(self, IsVersioned)
|
938
|
-
and self.is_latest
|
939
|
-
and not getattr(self, "_overwrite_versions", False)
|
940
|
-
):
|
941
|
-
new_latest = (
|
942
|
-
self.__class__.objects.using(self._state.db)
|
943
|
-
.filter(is_latest=False, uid__startswith=self.stem_uid)
|
944
|
-
.order_by("-created_at")
|
945
|
-
.first()
|
946
|
-
)
|
947
|
-
if new_latest is not None:
|
948
|
-
new_latest.is_latest = True
|
949
|
-
with transaction.atomic():
|
950
|
-
new_latest.save()
|
951
|
-
super().delete() # type: ignore
|
952
|
-
logger.warning(f"new latest version is: {new_latest}")
|
953
|
-
return None
|
954
|
-
super().delete()
|
969
|
+
delete_record(self, is_soft=False)
|
955
970
|
|
956
971
|
|
957
972
|
class Space(BaseSQLRecord):
|
@@ -1009,7 +1024,7 @@ class Space(BaseSQLRecord):
|
|
1009
1024
|
*args,
|
1010
1025
|
**kwargs,
|
1011
1026
|
):
|
1012
|
-
if "uid" not in kwargs:
|
1027
|
+
if not args and "uid" not in kwargs:
|
1013
1028
|
warn = False
|
1014
1029
|
msg = ""
|
1015
1030
|
isettings = setup_settings.instance
|
@@ -1183,9 +1198,8 @@ class SQLRecord(BaseSQLRecord, metaclass=Registry):
|
|
1183
1198
|
# change branch_id to trash
|
1184
1199
|
trash_branch_id = -1
|
1185
1200
|
if self.branch_id > trash_branch_id and permanent is not True:
|
1186
|
-
self
|
1187
|
-
|
1188
|
-
logger.warning(f"moved record to trash (`branch_id = -1`): {self}")
|
1201
|
+
delete_record(self, is_soft=True)
|
1202
|
+
logger.warning(f"moved record to trash (branch_id = -1): {self}")
|
1189
1203
|
return
|
1190
1204
|
|
1191
1205
|
# permanent delete
|
@@ -1194,11 +1208,11 @@ class SQLRecord(BaseSQLRecord, metaclass=Registry):
|
|
1194
1208
|
f"Record {self.uid} is already in trash! Are you sure you want to delete it from your"
|
1195
1209
|
" database? You can't undo this action. (y/n) "
|
1196
1210
|
)
|
1197
|
-
|
1211
|
+
confirm_delete = response == "y"
|
1198
1212
|
else:
|
1199
|
-
|
1213
|
+
confirm_delete = permanent
|
1200
1214
|
|
1201
|
-
if
|
1215
|
+
if confirm_delete:
|
1202
1216
|
if name_with_module == "Run":
|
1203
1217
|
from .run import delete_run_artifacts
|
1204
1218
|
|
@@ -0,0 +1,180 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: lamindb
|
3
|
+
Version: 1.11.2
|
4
|
+
Summary: A data framework for biology.
|
5
|
+
Author-email: Lamin Labs <open-source@lamin.ai>
|
6
|
+
Requires-Python: >=3.10,<3.14
|
7
|
+
Description-Content-Type: text/markdown
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
12
|
+
Requires-Dist: lamin_utils==0.15.0
|
13
|
+
Requires-Dist: lamin_cli==1.7.1
|
14
|
+
Requires-Dist: lamindb_setup[aws]==1.10.1
|
15
|
+
Requires-Dist: bionty>=1.7a1
|
16
|
+
Requires-Dist: wetlab>=1.5a1
|
17
|
+
Requires-Dist: nbproject==0.11.1
|
18
|
+
Requires-Dist: jupytext
|
19
|
+
Requires-Dist: nbconvert>=7.2.1
|
20
|
+
Requires-Dist: mistune!=3.1.0
|
21
|
+
Requires-Dist: pyyaml
|
22
|
+
Requires-Dist: pyarrow
|
23
|
+
Requires-Dist: pandera>=0.24.0
|
24
|
+
Requires-Dist: typing_extensions!=4.6.0
|
25
|
+
Requires-Dist: python-dateutil
|
26
|
+
Requires-Dist: pandas>=2.0.0
|
27
|
+
Requires-Dist: scipy<1.15.0
|
28
|
+
Requires-Dist: anndata>=0.8.0,<=0.12.1
|
29
|
+
Requires-Dist: fsspec
|
30
|
+
Requires-Dist: graphviz
|
31
|
+
Requires-Dist: psycopg2-binary
|
32
|
+
Requires-Dist: tomlkit ; extra == "dev"
|
33
|
+
Requires-Dist: line_profiler ; extra == "dev"
|
34
|
+
Requires-Dist: pre-commit ; extra == "dev"
|
35
|
+
Requires-Dist: nox ; extra == "dev"
|
36
|
+
Requires-Dist: laminci>=0.3 ; extra == "dev"
|
37
|
+
Requires-Dist: pytest>=6.0 ; extra == "dev"
|
38
|
+
Requires-Dist: coverage ; extra == "dev"
|
39
|
+
Requires-Dist: pytest-cov<7.0.0 ; extra == "dev"
|
40
|
+
Requires-Dist: mudata ; extra == "dev"
|
41
|
+
Requires-Dist: nbproject_test>=0.6.0 ; extra == "dev"
|
42
|
+
Requires-Dist: faker-biology ; extra == "dev"
|
43
|
+
Requires-Dist: pronto ; extra == "dev"
|
44
|
+
Requires-Dist: readfcs>=2.0.1 ; extra == "fcs"
|
45
|
+
Requires-Dist: lamindb_setup[gcp] ; extra == "gcp"
|
46
|
+
Requires-Dist: numcodecs<0.16.0 ; extra == "zarr"
|
47
|
+
Requires-Dist: zarr>=2.16.0,<3.0.0a0 ; extra == "zarr"
|
48
|
+
Project-URL: Home, https://github.com/laminlabs/lamindb
|
49
|
+
Provides-Extra: dev
|
50
|
+
Provides-Extra: fcs
|
51
|
+
Provides-Extra: gcp
|
52
|
+
Provides-Extra: zarr
|
53
|
+
|
54
|
+
[](https://github.com/laminlabs/lamindb)
|
55
|
+
[](https://codecov.io/gh/laminlabs/lamindb)
|
56
|
+
[](https://docs.lamin.ai)
|
57
|
+
[](https://docs.lamin.ai/summary.md)
|
58
|
+
[](https://pypi.org/project/lamindb)
|
59
|
+
[](https://pepy.tech/project/lamindb)
|
60
|
+
|
61
|
+
# LaminDB - A data lakehouse for biology
|
62
|
+
|
63
|
+
LaminDB is an open-source data lakehouse to enable learning at scale in biology.
|
64
|
+
It organizes datasets through validation & annotation and provides data lineage, queryability, and reproducibility on top of [FAIR](https://en.wikipedia.org/wiki/FAIR_data) data.
|
65
|
+
|
66
|
+
<details>
|
67
|
+
<summary>Why?</summary>
|
68
|
+
|
69
|
+
Reproducing analytical results or understanding how a dataset or model was created can be a pain.
|
70
|
+
Let alone training models on historical data, LIMS & ELN systems, orthogonal assays, or datasets generated by other teams.
|
71
|
+
Even maintaining a mere overview of a project's or team's datasets & analyses is harder than it sounds.
|
72
|
+
|
73
|
+
Biological datasets are typically managed with versioned storage systems, GUI-focused community or SaaS platforms, structureless data lakes, rigid data warehouses (SQL, monolithic arrays), and data lakehouses for tabular data.
|
74
|
+
|
75
|
+
LaminDB extends the lakehouse architecture to biological registries & datasets beyond tables (`DataFrame`, `AnnData`, `.zarr`, `.tiledbsoma`, ...) with enough structure to enable queries and enough freedom to keep the pace of R&D high.
|
76
|
+
Moreover, it provides context through data lineage -- tracing data and code, scientists and models -- and abstractions for biological domain knowledge and experimental metadata.
|
77
|
+
|
78
|
+
</details>
|
79
|
+
|
80
|
+
**Highlights.**
|
81
|
+
|
82
|
+
- **data lineage:** track inputs & outputs of notebooks, scripts, functions & pipelines with a single line of code
|
83
|
+
- **unified infrastructure:** access diverse storage locations (local, S3, GCP, ...), SQL databases (Postgres, SQLite) & ontologies
|
84
|
+
- **lakehouse capabilities**: manage, monitor & validate features, labels & dataset schemas; perform distributed queries and batch loading
|
85
|
+
- **biological data formats:** validate & annotate formats like `DataFrame`, `AnnData`, `MuData`, ... backed by `parquet`, `zarr`, HDF5, LanceDB, DuckDB, ...
|
86
|
+
- **biological entities**: organize experimental metadata & extensible ontologies in registries based on the Django ORM
|
87
|
+
- **reproducible & auditable:** auto-version & timestamp execution reports, source code & compute environments, attribute records to users
|
88
|
+
- **zero lock-in & scalable:** runs in your infrastructure; is _not_ a client for a rate-limited REST API
|
89
|
+
- **extendable:** create custom plug-ins for your own applications based on the Django ecosystem
|
90
|
+
- **integrations:** visualization tools like [vitessce](https://docs.lamin.ai/vitessce), workflow managers like [nextflow](https://docs.lamin.ai/nextflow) & [redun](https://docs.lamin.ai/redun), and [other tools](https://docs.lamin.ai/integrations)
|
91
|
+
- **production-ready:** used in BigPharma, BioTech, hospitals & top labs
|
92
|
+
|
93
|
+
LaminDB can be connected to LaminHub to serve as a [LIMS](https://en.wikipedia.org/wiki/Laboratory_information_management_system) for wetlab scientists, closing the drylab-wetlab feedback loop: [lamin.ai](https://lamin.ai)
|
94
|
+
|
95
|
+
## Docs
|
96
|
+
|
97
|
+
Copy [summary.md](https://docs.lamin.ai/summary.md) into an LLM chat and let AI explain or read the [docs](https://docs.lamin.ai).
|
98
|
+
|
99
|
+
## Setup
|
100
|
+
|
101
|
+
<!-- copied from quick-setup-lamindb.md -->
|
102
|
+
|
103
|
+
Install the `lamindb` Python package:
|
104
|
+
|
105
|
+
```shell
|
106
|
+
pip install lamindb
|
107
|
+
```
|
108
|
+
|
109
|
+
Create a LaminDB instance:
|
110
|
+
|
111
|
+
```shell
|
112
|
+
lamin init --storage ./quickstart-data # or s3://my-bucket, gs://my-bucket
|
113
|
+
```
|
114
|
+
|
115
|
+
Or if you have write access to an instance, connect to it:
|
116
|
+
|
117
|
+
```shell
|
118
|
+
lamin connect account/name
|
119
|
+
```
|
120
|
+
|
121
|
+
## Quickstart
|
122
|
+
|
123
|
+
<!-- copied from preface.md -->
|
124
|
+
|
125
|
+
Track a script or notebook run with source code, inputs, outputs, logs, and environment.
|
126
|
+
|
127
|
+
<!-- copied from py-quickstart.py -->
|
128
|
+
|
129
|
+
```python
|
130
|
+
import lamindb as ln
|
131
|
+
|
132
|
+
ln.track() # track a run
|
133
|
+
open("sample.fasta", "w").write(">seq1\nACGT\n")
|
134
|
+
ln.Artifact("sample.fasta", key="sample.fasta").save() # create an artifact
|
135
|
+
ln.finish() # finish the run
|
136
|
+
```
|
137
|
+
|
138
|
+
<!-- from here on, slight deviation from preface.md, where all this is treated in the walk through in more depth -->
|
139
|
+
|
140
|
+
This code snippet creates an artifact, which can store a dataset or model as a file or folder in various formats.
|
141
|
+
Running the snippet as a script (`python create-fasta.py`) produces the following data lineage.
|
142
|
+
|
143
|
+
```python
|
144
|
+
artifact = ln.Artifact.get(key="sample.fasta") # query artifact by key
|
145
|
+
artifact.view_lineage()
|
146
|
+
```
|
147
|
+
|
148
|
+
<img src="https://lamin-site-assets.s3.amazonaws.com/.lamindb/EkQATsQL5wqC95Wj0005.png" width="250">
|
149
|
+
|
150
|
+
You'll know how that artifact was created and what it's used for ([interactive visualization](https://lamin.ai/laminlabs/lamindata/artifact/8incOOgjn6F0K1TS)) in addition to capturing basic metadata:
|
151
|
+
|
152
|
+
```python
|
153
|
+
artifact.describe()
|
154
|
+
```
|
155
|
+
|
156
|
+
<img src="https://lamin-site-assets.s3.amazonaws.com/.lamindb/BOTCBgHDAvwglN3U0002.png" width="550">
|
157
|
+
|
158
|
+
You can organize datasets with validation & annotation of any kind of metadata to then access them via queries & search. Here is a more [comprehensive example](https://lamin.ai/laminlabs/lamindata/artifact/9K1dteZ6Qx0EXK8g).
|
159
|
+
|
160
|
+
<img src="https://lamin-site-assets.s3.amazonaws.com/.lamindb/6sofuDVvTANB0f480002.png" width="850">
|
161
|
+
|
162
|
+
To annotate an artifact with a label, use:
|
163
|
+
|
164
|
+
```python
|
165
|
+
my_experiment = ln.ULabel(name="My experiment").save() # create a label in the universal label ontology
|
166
|
+
artifact.ulabels.add(my_experiment) # annotate the artifact with the label
|
167
|
+
```
|
168
|
+
|
169
|
+
To query for a set of artifacts, use the `filter()` statement.
|
170
|
+
|
171
|
+
```python
|
172
|
+
ln.Artifact.filter(ulabels=my_experiment, suffix=".fasta").to_dataframe() # query by suffix and the ulabel we just created
|
173
|
+
ln.Artifact.filter(transform__key="create-fasta.py").to_dataframe() # query by the name of the script we just ran
|
174
|
+
```
|
175
|
+
|
176
|
+
If you have a structured dataset like a `DataFrame`, an `AnnData`, or another array, you can validate the content of the dataset (and parse annotations).
|
177
|
+
Here is an example for a dataframe: [docs.lamin.ai/introduction#validate-an-artifact](https://docs.lamin.ai/introduction#validate-an-artifact).
|
178
|
+
|
179
|
+
With a large body of validated datasets, you can then access data through distributed queries & batch streaming, see here: [docs.lamin.ai/arrays](https://docs.lamin.ai/arrays).
|
180
|
+
|
@@ -1,8 +1,8 @@
|
|
1
|
-
lamindb/__init__.py,sha256=
|
2
|
-
lamindb/_finish.py,sha256=
|
1
|
+
lamindb/__init__.py,sha256=HGxNpCYe-NeHQHiQXY8bEEfDXbH0zN_ucGrXIEO7cBw,3241
|
2
|
+
lamindb/_finish.py,sha256=4KkFyb9d-GEGjDw_zDrnGt_bq3auQ_OQu0hV-2U73AQ,21355
|
3
3
|
lamindb/_tracked.py,sha256=fls9yd7EEGO9Ni51kA_pcBkeLpzm2HZrWtwYGQequNE,4395
|
4
4
|
lamindb/_view.py,sha256=GOKTfwnEaly9fdeWo9SlhYRc3UWEyLDmTlIUzjFXMYY,4960
|
5
|
-
lamindb/errors.py,sha256=
|
5
|
+
lamindb/errors.py,sha256=kHKRWXPGQPnzTo0D0vQxJjY_8bGH_Xx1IGFgM-dYN3E,2277
|
6
6
|
lamindb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
lamindb/base/__init__.py,sha256=u623ZDoNCwwyLLt_Jhtp3KDeum0LOg6cwAqn5TEgz_E,313
|
8
8
|
lamindb/base/dtypes.py,sha256=Bfrca8Slb3vIAIMLd-mjG4_9bTHz-LlThSIUHvfNmhA,3189
|
@@ -13,7 +13,7 @@ lamindb/base/uids.py,sha256=cLBi5mIlsf1ltkTb17r1FLzlOjlGmjvsCygoVJHQ-A8,2116
|
|
13
13
|
lamindb/base/users.py,sha256=8MSmAvCKoUF15YsDE6BGLBXsFWpfoEEg8iDTKZ7kD48,848
|
14
14
|
lamindb/core/__init__.py,sha256=I9F-GugBMZwFLpUPb1MXyLfccIVAj021Gb_00h_18MY,633
|
15
15
|
lamindb/core/_compat.py,sha256=NLnKk1qk4xdgMV-QwFDnBnbio02ujjlF86icvhpdv4c,2029
|
16
|
-
lamindb/core/_context.py,sha256=
|
16
|
+
lamindb/core/_context.py,sha256=wPRNcQ0tPrwvYkYbHxZz0VzdxeBZEuorWOIqpucnbFk,40444
|
17
17
|
lamindb/core/_mapped_collection.py,sha256=osquwC6ee0wJ_I6O-8AZwnQUa_r9zqa0MN82Q-nBI3Y,25746
|
18
18
|
lamindb/core/_settings.py,sha256=519bOSopRb7_nE874KDJB263v1xFlk4TOqhBNNeO4yw,10992
|
19
19
|
lamindb/core/_sync_git.py,sha256=Z7keuyS5X7CAj285sEbZIFExZF9mtjGH8DzKwz3xhHw,5881
|
@@ -37,25 +37,25 @@ lamindb/core/subsettings/_annotation_settings.py,sha256=o-yTYw-NmjFmtehbKU8qnf7t
|
|
37
37
|
lamindb/core/subsettings/_creation_settings.py,sha256=NGHWKqCFSzVNBxAr2VnmdYguiFdW29XUK7T9wRsVshg,906
|
38
38
|
lamindb/curators/__init__.py,sha256=WLnaVxrhQGZxGB3pjg-SM4oUu6DaKA78S_J3BfVKLEg,496
|
39
39
|
lamindb/curators/_legacy.py,sha256=Ay2nd4u2OPL59aYC6rKNE9YpfVTC-MMPvnyzS3fM6xg,55172
|
40
|
-
lamindb/curators/core.py,sha256=
|
40
|
+
lamindb/curators/core.py,sha256=PbkRxt8ngAxnfTXXxKNKCCEgtUxoyp3_I2f4UVyB7tE,78316
|
41
41
|
lamindb/examples/__init__.py,sha256=f0pBxijIA26ULUBnsP2sa1e4CLqMTeUUEqNeINJIf9o,179
|
42
42
|
lamindb/examples/cellxgene/__init__.py,sha256=0itpr7sthjaZAbL5nGTVTisL5OeP-3WqKFr8zyDWxYM,247
|
43
|
-
lamindb/examples/cellxgene/_cellxgene.py,sha256=
|
43
|
+
lamindb/examples/cellxgene/_cellxgene.py,sha256=Vgot8L9ZmaX_PwOlsghmVKsnstxj979yRGjWNtDclUw,12885
|
44
44
|
lamindb/examples/cellxgene/cellxgene_schema_versions.csv,sha256=IbtgPbrMksqr3q9z0t2-D1ZTPnMO_i29W7crtgpN52w,2534
|
45
|
-
lamindb/examples/croissant/__init__.py,sha256=
|
45
|
+
lamindb/examples/croissant/__init__.py,sha256=dfkL6MJ-L0qdPd4ZzGlMAlQHCB5wIGpSuQVwXBEeQwQ,2322
|
46
46
|
lamindb/examples/croissant/mini_immuno.anndata.zarr_metadata.json,sha256=XhY4wnFyMoK4Thkaolh2yJxtU6sX0bdFsJvRvt942k8,2921
|
47
47
|
lamindb/examples/datasets/__init__.py,sha256=SKeX5kgjfXtNkUek4GfLYsgn-bGO8UsuF4Qf3R_zN-4,1988
|
48
|
-
lamindb/examples/datasets/_core.py,sha256=
|
48
|
+
lamindb/examples/datasets/_core.py,sha256=JIHf8NrvGYHYtt-ILxCIb4tOQUIPpFBXw357fDlbU2I,21553
|
49
49
|
lamindb/examples/datasets/_fake.py,sha256=BZF9R_1iF0HDnvtZNqL2FtsjSMuqDIfuFxnw_LJYIh4,953
|
50
50
|
lamindb/examples/datasets/_small.py,sha256=wHJb6eXzkQC_Ma8VqX7Orb3nGuAbyNdrr0jxJ93jjxc,4852
|
51
|
-
lamindb/examples/datasets/mini_immuno.py,sha256=
|
51
|
+
lamindb/examples/datasets/mini_immuno.py,sha256=ZEL9T4zhCKm8ggqU7VVhuihVKPR3MmlkJNOtdygH2v4,6107
|
52
52
|
lamindb/examples/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
|
-
lamindb/examples/fixtures/sheets.py,sha256=
|
53
|
+
lamindb/examples/fixtures/sheets.py,sha256=YrkHLSjXIzIJlvZFuYppGqDcQKif93O37CcRobZkNDQ,9506
|
54
54
|
lamindb/examples/schemas/__init__.py,sha256=NPDp7VjMOHStEIthx3xW9NSHtY7jnnMzrNPcSDgxT3M,241
|
55
55
|
lamindb/examples/schemas/_anndata.py,sha256=TAQrnBLZhH4TgbznrJDdGK_Gze6cf1MvyXuCcKIvb1g,1210
|
56
56
|
lamindb/examples/schemas/_simple.py,sha256=Dspj5QRmv241IstBxuc1E1Q5YeEqTOnOvakg7ChPj1k,911
|
57
57
|
lamindb/integrations/__init__.py,sha256=Zh0ROuRmob1QGV2mCo3A7cFmdheJGq4CUdo7G16pRHU,286
|
58
|
-
lamindb/integrations/_croissant.py,sha256=
|
58
|
+
lamindb/integrations/_croissant.py,sha256=RNX6dDPPun1QG6t456GxK19t071_FJWzwmUXiVDkHFE,5200
|
59
59
|
lamindb/integrations/_vitessce.py,sha256=s2F8KPpYVG0zUOTaDJgH1XAJtQDg1zrD_SxC4ZHUkHk,4035
|
60
60
|
lamindb/migrations/0069_squashed.py,sha256=7XdiRW0MBtr3Jck9dbIy_9qxmB_sjtLM1SH9x062d2k,62631
|
61
61
|
lamindb/migrations/0070_lamindbv1_migrate_data.py,sha256=tyq_xi6U8TXi9C2Raf6v_UTtfyfqQOUIFJzYj4oCgAE,2429
|
@@ -110,30 +110,30 @@ lamindb/migrations/0118_alter_recordproject_value_projectrecord.py,sha256=aNC_o3
|
|
110
110
|
lamindb/migrations/0119_rename_records_project_linked_in_records.py,sha256=Feh4rCfoGD4kiGG-sk_IQx7cplDn-yVIlzI5FzE8utI,688
|
111
111
|
lamindb/migrations/0119_squashed.py,sha256=mY1gpmPqEDEZjjPFgiDJSSGhP9TmNi-T7b5bNmRDztM,166975
|
112
112
|
lamindb/migrations/0120_add_record_fk_constraint.py,sha256=KvYuA0ET6hoVugu9gwAk29_dSM5HKeOzNvQARjjyK5U,1815
|
113
|
-
lamindb/migrations/0121_recorduser.py,sha256=
|
113
|
+
lamindb/migrations/0121_recorduser.py,sha256=aDz6P-dSUn2bsLKuNPpMk2bSY1DeDftQPBBIVtNCpAI,1980
|
114
114
|
lamindb/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
115
|
-
lamindb/models/__init__.py,sha256=
|
115
|
+
lamindb/models/__init__.py,sha256=Owupnxv_JnoOenlSpn6iT997VRnwayBowh5MAfT-Eqs,2484
|
116
116
|
lamindb/models/_describe.py,sha256=Co6_whJG7Pm2Sl6YDmGoYL28XZyJ7VqICHTfgGedxvw,10919
|
117
117
|
lamindb/models/_django.py,sha256=go0sAhIGJ-JkYe5OMviWUm-ZwHdqDuBgnPbFvncA-lQ,12347
|
118
|
-
lamindb/models/_feature_manager.py,sha256=
|
118
|
+
lamindb/models/_feature_manager.py,sha256=35CylDvaq-awUTSpjqgMDyBU78wfkRou3OteUfmtZo0,57502
|
119
119
|
lamindb/models/_from_values.py,sha256=ymR8b0Qa3ZiTFTIuMsFYiBNH16ggDPlYeFjCaFgGETA,13372
|
120
120
|
lamindb/models/_is_versioned.py,sha256=zCnn5Z5HehBlKX-NXFhqfr3lbVOMRhlvG4ljtLbXl4A,7590
|
121
121
|
lamindb/models/_label_manager.py,sha256=12RV8uEpWILGUkNHb7JMccF341ArmrIbHfI9KAo742Q,12118
|
122
122
|
lamindb/models/_relations.py,sha256=zHYLujy9vkuB9jVq5844TpzLSP__iYNCQcsl-FzK1Jw,3700
|
123
|
-
lamindb/models/artifact.py,sha256=
|
124
|
-
lamindb/models/artifact_set.py,sha256=
|
123
|
+
lamindb/models/artifact.py,sha256=L0DF6HFU1MXHXC3MqE7vWQrRefg4T9A5SFkzA4Sh-J8,125097
|
124
|
+
lamindb/models/artifact_set.py,sha256=TfRxmuY9mRzkIeG_vWIDxq4_R_efnXuTbz4xxz7S5Kg,5389
|
125
125
|
lamindb/models/can_curate.py,sha256=_w7k8-gPju7owHzX79phtcL7VRy7wAaz-90MzOz8UUQ,29313
|
126
126
|
lamindb/models/collection.py,sha256=OqPhDppzCx2y7xEqtmV83el4iNrvOO1KvkE-y8ZEvm4,27372
|
127
127
|
lamindb/models/feature.py,sha256=6kI3UZMp3gBi75NhXBp_jn-1tRlc42YdJOEJFNgjtNo,41814
|
128
128
|
lamindb/models/has_parents.py,sha256=Ok-Tsh4-oBDjkyevyMSuOCb0mzDiswiO_0ufTqWz8o4,20341
|
129
129
|
lamindb/models/project.py,sha256=AhaY24iE8ilpS5dRFYzY6xQNVlqPHWMk72ib2OI_N8U,18732
|
130
130
|
lamindb/models/query_manager.py,sha256=zjO31kbj1t08WTxeZB9-BPjooz6axh06EFu90dfvpSA,11358
|
131
|
-
lamindb/models/query_set.py,sha256=
|
132
|
-
lamindb/models/record.py,sha256=
|
133
|
-
lamindb/models/run.py,sha256=
|
134
|
-
lamindb/models/save.py,sha256=
|
131
|
+
lamindb/models/query_set.py,sha256=zwMlYRfjvAQ4NjIKpk19ipiP43UhGiUoU2wxntnBDUY,39591
|
132
|
+
lamindb/models/record.py,sha256=2eKEDqpiX5-aN2kUVXLuTVvQUspqQ5h10onbQM6Ta7g,13041
|
133
|
+
lamindb/models/run.py,sha256=LVZ2z5QV4aVYYsqGcLmMfqvPpKj4EGGHVts_RR8_c-E,14443
|
134
|
+
lamindb/models/save.py,sha256=CEifxocJuoLIuapqtiGk-eKvXfQSK4v389CWBo4FxOA,17264
|
135
135
|
lamindb/models/schema.py,sha256=LQuPQhyLitloRGxq6DWZMHcR-xDZY1NctPHjrC6t1iw,49827
|
136
|
-
lamindb/models/sqlrecord.py,sha256=
|
136
|
+
lamindb/models/sqlrecord.py,sha256=kL2YS0lAENLXVMC5bzQuOZrRpujdLsBCJCf0sX_4PlE,72686
|
137
137
|
lamindb/models/storage.py,sha256=n7jth0RQ19K0W8ICbrAO942d5jBm1-h7DsrSjMJgAB0,15551
|
138
138
|
lamindb/models/transform.py,sha256=FcIPqmSk1hahg2Cr8q6lm1kKpbdvu2JUceSlPIV9Dww,12780
|
139
139
|
lamindb/models/ulabel.py,sha256=UznidEEoiIns_KetWgCbDejXuM5hmzF6F49yqf2kLpQ,9495
|
@@ -142,7 +142,7 @@ lamindb/setup/_switch.py,sha256=njZJN__JOhVrBFGClQG1wobdhJJp6l_XzPGKtKSCrfU,434
|
|
142
142
|
lamindb/setup/core/__init__.py,sha256=SevlVrc2AZWL3uALbE5sopxBnIZPWZ1IB0NBDudiAL8,167
|
143
143
|
lamindb/setup/errors/__init__.py,sha256=bAHTxOUJW1rm4zpF0Pvqkftn8W6iMGnQ-uyNBu13Nfg,171
|
144
144
|
lamindb/setup/types/__init__.py,sha256=ATaosOi6q-cDWB52T69_sRmLMqj8cHfc-vljzZsrJNw,169
|
145
|
-
lamindb-1.
|
146
|
-
lamindb-1.
|
147
|
-
lamindb-1.
|
148
|
-
lamindb-1.
|
145
|
+
lamindb-1.11.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
146
|
+
lamindb-1.11.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
147
|
+
lamindb-1.11.2.dist-info/METADATA,sha256=69LKvBDk40m1gfwl-DIpwIxQqCxNt5zPWf0zuIz9pHc,8552
|
148
|
+
lamindb-1.11.2.dist-info/RECORD,,
|