lamindb 1.11.3__py3-none-any.whl → 1.12.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 +8 -14
- lamindb/_tracked.py +2 -0
- lamindb/base/types.py +1 -3
- lamindb/core/_context.py +16 -31
- lamindb/core/_mapped_collection.py +2 -2
- lamindb/core/storage/paths.py +5 -3
- lamindb/curators/core.py +15 -4
- lamindb/examples/__init__.py +3 -1
- lamindb/examples/croissant/__init__.py +3 -1
- lamindb/examples/mlflow/__init__.py +38 -0
- lamindb/examples/wandb/__init__.py +40 -0
- lamindb/integrations/__init__.py +26 -0
- lamindb/integrations/_lightning.py +87 -0
- lamindb/migrations/0120_add_record_fk_constraint.py +1 -1
- lamindb/migrations/0122_remove_personproject_person_and_more.py +219 -0
- lamindb/migrations/0123_alter_artifact_description_alter_branch_description_and_more.py +82 -0
- lamindb/migrations/0124_page_artifact_page_collection_page_feature_page_and_more.py +15 -0
- lamindb/migrations/0125_artifact_is_locked_collection_is_locked_and_more.py +79 -0
- lamindb/migrations/0126_alter_artifact_is_locked_alter_collection_is_locked_and_more.py +105 -0
- lamindb/migrations/0127_alter_run_status_code_feature_dtype.py +31 -0
- lamindb/migrations/0128_artifact__real_key.py +21 -0
- lamindb/migrations/0129_remove_feature_page_remove_project_page_and_more.py +779 -0
- lamindb/migrations/0130_branch_space_alter_artifactblock_artifact_and_more.py +170 -0
- lamindb/migrations/0131_record_unique_name_type_space.py +18 -0
- lamindb/migrations/0132_record_parents_record_reference_and_more.py +61 -0
- lamindb/migrations/0133_artifactuser_artifact_users.py +108 -0
- lamindb/migrations/{0119_squashed.py → 0133_squashed.py} +1211 -322
- lamindb/models/__init__.py +14 -4
- lamindb/models/_django.py +1 -2
- lamindb/models/_feature_manager.py +1 -0
- lamindb/models/_is_versioned.py +14 -16
- lamindb/models/_relations.py +7 -0
- lamindb/models/artifact.py +99 -56
- lamindb/models/artifact_set.py +20 -3
- lamindb/models/block.py +174 -0
- lamindb/models/can_curate.py +7 -9
- lamindb/models/collection.py +9 -9
- lamindb/models/feature.py +38 -38
- lamindb/models/has_parents.py +15 -6
- lamindb/models/project.py +44 -99
- lamindb/models/query_manager.py +1 -1
- lamindb/models/query_set.py +36 -8
- lamindb/models/record.py +169 -46
- lamindb/models/run.py +44 -10
- lamindb/models/save.py +7 -7
- lamindb/models/schema.py +9 -2
- lamindb/models/sqlrecord.py +87 -35
- lamindb/models/storage.py +13 -3
- lamindb/models/transform.py +7 -2
- lamindb/models/ulabel.py +6 -23
- {lamindb-1.11.3.dist-info → lamindb-1.12.1.dist-info}/METADATA +18 -21
- {lamindb-1.11.3.dist-info → lamindb-1.12.1.dist-info}/RECORD +54 -38
- {lamindb-1.11.3.dist-info → lamindb-1.12.1.dist-info}/LICENSE +0 -0
- {lamindb-1.11.3.dist-info → lamindb-1.12.1.dist-info}/WHEEL +0 -0
lamindb/models/can_curate.py
CHANGED
@@ -66,7 +66,7 @@ def _inspect(
|
|
66
66
|
values = _concat_lists(values)
|
67
67
|
|
68
68
|
field_str = get_name_field(cls, field=field)
|
69
|
-
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.
|
69
|
+
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.filter().all()
|
70
70
|
registry = queryset.model
|
71
71
|
model_name = registry._meta.model.__name__
|
72
72
|
if isinstance(source, SQLRecord):
|
@@ -170,7 +170,7 @@ def _validate(
|
|
170
170
|
|
171
171
|
field_str = get_name_field(cls, field=field)
|
172
172
|
|
173
|
-
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.
|
173
|
+
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.filter().all()
|
174
174
|
registry = queryset.model
|
175
175
|
if isinstance(source, SQLRecord):
|
176
176
|
_check_if_record_in_db(source, queryset.db)
|
@@ -191,10 +191,8 @@ def _validate(
|
|
191
191
|
)
|
192
192
|
if field_values.empty:
|
193
193
|
if not mute:
|
194
|
-
msg =
|
195
|
-
|
196
|
-
)
|
197
|
-
if hasattr(cls, "source_id"):
|
194
|
+
msg = f"Your {queryset.model.__name__} registry is empty, consider populating it first!"
|
195
|
+
if hasattr(queryset.model, "source_id"):
|
198
196
|
msg += "\n → use `.import_source()` to import records from a source, e.g. a public ontology"
|
199
197
|
logger.warning(msg)
|
200
198
|
return np.array([False] * len(values))
|
@@ -238,7 +236,7 @@ def _standardize(
|
|
238
236
|
return_field_str = get_name_field(
|
239
237
|
cls, field=field if return_field is None else return_field
|
240
238
|
)
|
241
|
-
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.
|
239
|
+
queryset = cls.all() if isinstance(cls, (QuerySet, Manager)) else cls.filter().all()
|
242
240
|
registry = queryset.model
|
243
241
|
if isinstance(source, SQLRecord):
|
244
242
|
_check_if_record_in_db(source, queryset.db)
|
@@ -358,7 +356,7 @@ def _add_or_remove_synonyms(
|
|
358
356
|
from IPython.display import display
|
359
357
|
|
360
358
|
syns_all = (
|
361
|
-
record.__class__.
|
359
|
+
record.__class__.filter().exclude(synonyms="").exclude(synonyms=None).all() # type: ignore
|
362
360
|
)
|
363
361
|
if len(syns_all) == 0:
|
364
362
|
return
|
@@ -591,7 +589,7 @@ class CanCurate:
|
|
591
589
|
A list of validated records. For bionty registries. Also returns knowledge-coupled records.
|
592
590
|
|
593
591
|
Notes:
|
594
|
-
For more info, see tutorial: :doc:`docs:
|
592
|
+
For more info, see tutorial: :doc:`docs:manage-ontologies`.
|
595
593
|
|
596
594
|
Example::
|
597
595
|
|
lamindb/models/collection.py
CHANGED
@@ -49,6 +49,7 @@ if TYPE_CHECKING:
|
|
49
49
|
from pyarrow.dataset import Dataset as PyArrowDataset
|
50
50
|
|
51
51
|
from ..core.storage import UPath
|
52
|
+
from .block import CollectionBlock
|
52
53
|
from .project import Project, Reference
|
53
54
|
from .query_set import QuerySet
|
54
55
|
from .transform import Transform
|
@@ -174,7 +175,7 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
174
175
|
# below is the only case in which we use a TextField
|
175
176
|
# for description; we do so because users had descriptions exceeding 255 chars
|
176
177
|
# in their instances
|
177
|
-
description: str | None = TextField(null=True
|
178
|
+
description: str | None = TextField(null=True)
|
178
179
|
"""A description or title."""
|
179
180
|
hash: str | None = CharField(
|
180
181
|
max_length=HASH_LENGTH, db_index=True, null=True, unique=True
|
@@ -224,6 +225,8 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
224
225
|
"""Linked projects."""
|
225
226
|
references: Reference
|
226
227
|
"""Linked references."""
|
228
|
+
blocks: CollectionBlock
|
229
|
+
"""Blocks that annotate this collection."""
|
227
230
|
|
228
231
|
@overload
|
229
232
|
def __init__(
|
@@ -437,7 +440,6 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
437
440
|
|
438
441
|
dataframe = _open_dataframe(paths, engine=engine, **kwargs)
|
439
442
|
# track only if successful
|
440
|
-
# is it really needed if tracking is done in self.ordered_artifacts.all()? - Sergei
|
441
443
|
_track_run_input(self, is_run_input)
|
442
444
|
return dataframe
|
443
445
|
|
@@ -538,24 +540,23 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
538
540
|
dtype,
|
539
541
|
)
|
540
542
|
# track only if successful
|
541
|
-
# is it really needed if tracking is done in self.ordered_artifacts.all()? - Sergei
|
542
543
|
_track_run_input(self, is_run_input)
|
543
544
|
return ds
|
544
545
|
|
545
546
|
def cache(self, is_run_input: bool | None = None) -> list[UPath]:
|
546
547
|
"""Download cloud artifacts in collection to local cache.
|
547
548
|
|
548
|
-
Follows
|
549
|
+
Follows syncing logic: only downloads outdated artifacts.
|
549
550
|
|
550
|
-
Returns paths to locally cached on-disk artifacts.
|
551
|
+
Returns ordered paths to locally cached on-disk artifacts via `.ordered_artifacts.all()`:
|
551
552
|
|
552
553
|
Args:
|
553
554
|
is_run_input: Whether to track this collection as run input.
|
554
555
|
"""
|
555
556
|
path_list = []
|
556
557
|
for artifact in self.ordered_artifacts.all():
|
557
|
-
|
558
|
-
|
558
|
+
# do not want to track data lineage on the artifact level
|
559
|
+
path_list.append(artifact.cache(is_run_input=False))
|
559
560
|
_track_run_input(self, is_run_input)
|
560
561
|
return path_list
|
561
562
|
|
@@ -573,7 +574,6 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
573
574
|
artifacts = self.ordered_artifacts.all()
|
574
575
|
concat_object = _load_concat_artifacts(artifacts, join, **kwargs)
|
575
576
|
# only call it here because there might be errors during load or concat
|
576
|
-
# is it really needed if tracking is done in self.ordered_artifacts.all()? - Sergei
|
577
577
|
_track_run_input(self, is_run_input)
|
578
578
|
return concat_object
|
579
579
|
|
@@ -640,7 +640,7 @@ class Collection(SQLRecord, IsVersioned, TracksRun, TracksUpdates):
|
|
640
640
|
you non-deterministic order.
|
641
641
|
|
642
642
|
Using the property `.ordered_artifacts` allows to iterate through a set
|
643
|
-
that's ordered
|
643
|
+
that's ordered by the order of the list that created the collection.
|
644
644
|
"""
|
645
645
|
return self.artifacts.order_by("links_collection__id")
|
646
646
|
|
lamindb/models/feature.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import importlib
|
4
|
+
import warnings
|
4
5
|
from typing import TYPE_CHECKING, Any, get_args, overload
|
5
6
|
|
6
7
|
import numpy as np
|
@@ -43,6 +44,8 @@ from .sqlrecord import BaseSQLRecord, Registry, SQLRecord, _get_record_kwargs
|
|
43
44
|
if TYPE_CHECKING:
|
44
45
|
from collections.abc import Iterable
|
45
46
|
|
47
|
+
from .block import FeatureBlock
|
48
|
+
from .projects import Project
|
46
49
|
from .schema import Schema
|
47
50
|
|
48
51
|
FEATURE_DTYPES = set(get_args(Dtype))
|
@@ -538,7 +541,7 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
538
541
|
custom registries to manage high-level derived features like gene sets.
|
539
542
|
|
540
543
|
See Also:
|
541
|
-
:meth:`~lamindb.Feature.
|
544
|
+
:meth:`~lamindb.Feature.from_dataframe`
|
542
545
|
Create feature records from DataFrame.
|
543
546
|
:attr:`~lamindb.Artifact.features`
|
544
547
|
Feature manager of an artifact or collection.
|
@@ -600,6 +603,12 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
600
603
|
class Meta(SQLRecord.Meta, TracksRun.Meta, TracksUpdates.Meta):
|
601
604
|
abstract = False
|
602
605
|
app_label = "lamindb"
|
606
|
+
constraints = [
|
607
|
+
models.CheckConstraint(
|
608
|
+
condition=models.Q(is_type=True) | models.Q(dtype__isnull=False),
|
609
|
+
name="dtype_not_null_when_is_type_false",
|
610
|
+
)
|
611
|
+
]
|
603
612
|
|
604
613
|
_name_field: str = "name"
|
605
614
|
_aux_fields: dict[str, tuple[str, type]] = {
|
@@ -616,7 +625,8 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
616
625
|
"""Universal id, valid across DB instances."""
|
617
626
|
name: str = CharField(max_length=150, db_index=True)
|
618
627
|
"""Name of feature."""
|
619
|
-
dtype
|
628
|
+
# dtype can be null if is_type is True
|
629
|
+
dtype: Dtype = CharField(db_index=True, null=True)
|
620
630
|
"""Data type (:class:`~lamindb.base.types.Dtype`)."""
|
621
631
|
type: Feature | None = ForeignKey(
|
622
632
|
"self", PROTECT, null=True, related_name="features"
|
@@ -631,7 +641,7 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
631
641
|
"""Distinguish types from instances of the type."""
|
632
642
|
unit: str | None = CharField(max_length=30, db_index=True, null=True)
|
633
643
|
"""Unit of measure, ideally SI (`m`, `s`, `kg`, etc.) or 'normalized' etc. (optional)."""
|
634
|
-
description: str | None =
|
644
|
+
description: str | None = TextField(null=True)
|
635
645
|
"""A description."""
|
636
646
|
array_rank: int = models.SmallIntegerField(default=0, db_index=True)
|
637
647
|
"""Rank of feature.
|
@@ -684,6 +694,10 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
684
694
|
# backward fields
|
685
695
|
values: FeatureValue
|
686
696
|
"""Values for this feature."""
|
697
|
+
projects: Project
|
698
|
+
"""Annotating projects."""
|
699
|
+
blocks: FeatureBlock
|
700
|
+
"""Blocks that annotate this feature."""
|
687
701
|
|
688
702
|
@overload
|
689
703
|
def __init__(
|
@@ -828,71 +842,57 @@ class Feature(SQLRecord, CanCurate, TracksRun, TracksUpdates):
|
|
828
842
|
field: FieldAttr | None = None,
|
829
843
|
*,
|
830
844
|
str_as_cat: bool | None = None,
|
845
|
+
type: Feature | None = None,
|
831
846
|
mute: bool = False,
|
832
847
|
) -> SQLRecordList:
|
833
848
|
"""Create Feature records for dictionary keys.
|
834
849
|
|
835
850
|
Args:
|
836
851
|
dictionary: Source dictionary to extract key information from
|
837
|
-
field: FieldAttr for Feature model validation, defaults to Feature.name
|
838
|
-
str_as_cat:
|
852
|
+
field: FieldAttr for Feature model validation, defaults to `Feature.name`
|
853
|
+
str_as_cat: Deprecated. Will be removed in LaminDB 2.0.0.
|
854
|
+
Create features explicitly with dtype='cat' for categorical values.
|
855
|
+
type: Feature type of all created features
|
839
856
|
mute: Whether to mute dtype inference and feature creation warnings
|
840
857
|
"""
|
841
858
|
from lamindb.models._feature_manager import infer_feature_type_convert_json
|
842
859
|
|
860
|
+
if str_as_cat is not None:
|
861
|
+
warnings.warn(
|
862
|
+
"`str_as_cat` is deprecated and will be removed in LaminDB 2.0.0. "
|
863
|
+
"Create features explicitly with dtype='cat' for categorical values.",
|
864
|
+
DeprecationWarning,
|
865
|
+
stacklevel=2,
|
866
|
+
)
|
867
|
+
|
843
868
|
field = Feature.name if field is None else field
|
844
869
|
registry = field.field.model # type: ignore
|
845
870
|
if registry != Feature:
|
846
871
|
raise ValueError("field must be a Feature FieldAttr!")
|
847
872
|
|
848
873
|
dtypes = {}
|
849
|
-
ambiguous_keys = []
|
850
874
|
for key, value in dictionary.items():
|
851
875
|
dtype, _, message = infer_feature_type_convert_json(key, value, mute=mute)
|
852
|
-
|
853
876
|
if dtype == "cat ? str":
|
854
877
|
if str_as_cat is None:
|
855
|
-
ambiguous_keys.append(
|
856
|
-
(key, "str or cat", message.strip("# ") if message else "")
|
857
|
-
)
|
858
|
-
continue
|
859
|
-
if str_as_cat:
|
860
|
-
dtype = "cat"
|
861
|
-
else:
|
862
878
|
dtype = "str"
|
863
|
-
|
879
|
+
else:
|
880
|
+
dtype = "cat" if str_as_cat else "str"
|
864
881
|
elif dtype == "list[cat ? str]":
|
865
882
|
if str_as_cat is None:
|
866
|
-
ambiguous_keys.append(
|
867
|
-
(
|
868
|
-
key,
|
869
|
-
"list[str] or list[cat]",
|
870
|
-
message.strip("# ") if message else "",
|
871
|
-
)
|
872
|
-
)
|
873
|
-
continue
|
874
|
-
if str_as_cat:
|
875
|
-
dtype = "list[cat]"
|
876
|
-
else:
|
877
883
|
dtype = "list[str]"
|
878
|
-
|
884
|
+
else:
|
885
|
+
dtype = "list[cat]" if str_as_cat else "list[str]"
|
879
886
|
dtypes[key] = dtype
|
880
887
|
|
881
|
-
if ambiguous_keys:
|
882
|
-
error_msg = "Ambiguous dtypes detected. Please pass `str_as_cat` parameter or create features explicitly:\n"
|
883
|
-
for key, options, msg in ambiguous_keys:
|
884
|
-
error_msg += f" '{key}': {options}"
|
885
|
-
if msg:
|
886
|
-
error_msg += f" ({msg})"
|
887
|
-
error_msg += "\n"
|
888
|
-
error_msg += "\nUse `str_as_cat=True` to treat strings as categorical, or `str_as_cat=False` for plain strings."
|
889
|
-
raise ValueError(error_msg)
|
890
|
-
|
891
888
|
if mute:
|
892
889
|
original_verbosity = logger._verbosity
|
893
890
|
logger.set_verbosity(0)
|
894
891
|
try:
|
895
|
-
features = [
|
892
|
+
features = [
|
893
|
+
Feature(name=key, dtype=dtype, type=type)
|
894
|
+
for key, dtype in dtypes.items()
|
895
|
+
] # type: ignore
|
896
896
|
assert len(features) == len(dictionary) # noqa: S101
|
897
897
|
return SQLRecordList(features)
|
898
898
|
finally:
|
lamindb/models/has_parents.py
CHANGED
@@ -42,13 +42,22 @@ def _query_relatives(
|
|
42
42
|
attr: str,
|
43
43
|
cls: type[HasParents],
|
44
44
|
) -> QuerySet:
|
45
|
-
|
46
|
-
|
45
|
+
from .query_set import get_default_branch_ids
|
46
|
+
|
47
|
+
branch_ids = get_default_branch_ids()
|
48
|
+
|
49
|
+
def query_relatives_on_branches(records, attr, cls) -> QuerySet:
|
50
|
+
relatives = cls.objects.none() # type: ignore
|
51
|
+
if len(records) == 0:
|
52
|
+
return relatives
|
53
|
+
for record in records:
|
54
|
+
relatives = relatives.union(
|
55
|
+
getattr(record, attr).filter(branch_id__in=branch_ids)
|
56
|
+
)
|
57
|
+
relatives = relatives.union(query_relatives_on_branches(relatives, attr, cls))
|
47
58
|
return relatives
|
48
|
-
|
49
|
-
|
50
|
-
relatives = relatives.union(_query_relatives(relatives, attr, cls))
|
51
|
-
return relatives
|
59
|
+
|
60
|
+
return query_relatives_on_branches(records, attr, cls)
|
52
61
|
|
53
62
|
|
54
63
|
class HasParents:
|
lamindb/models/project.py
CHANGED
@@ -12,14 +12,13 @@ from lamindb.base.fields import (
|
|
12
12
|
CharField,
|
13
13
|
DateField,
|
14
14
|
DateTimeField,
|
15
|
-
EmailField,
|
16
15
|
ForeignKey,
|
17
16
|
TextField,
|
18
17
|
URLField,
|
19
18
|
)
|
20
19
|
from lamindb.base.users import current_user_id
|
21
20
|
|
22
|
-
from ..base.ids import
|
21
|
+
from ..base.ids import base62_12
|
23
22
|
from .artifact import Artifact
|
24
23
|
from .can_curate import CanCurate
|
25
24
|
from .collection import Collection
|
@@ -35,59 +34,7 @@ if TYPE_CHECKING:
|
|
35
34
|
from datetime import date as DateType
|
36
35
|
from datetime import datetime
|
37
36
|
|
38
|
-
|
39
|
-
class Person(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
40
|
-
"""People such as authors of a study or collaborators in a project.
|
41
|
-
|
42
|
-
This registry is distinct from `User` and exists for project management.
|
43
|
-
|
44
|
-
You'll soon be able to conveniently create persons from users.
|
45
|
-
|
46
|
-
Example:
|
47
|
-
>>> person = Person(
|
48
|
-
... name="Jane Doe",
|
49
|
-
... email="jane.doe@example.com",
|
50
|
-
... internal=True,
|
51
|
-
... ).save()
|
52
|
-
"""
|
53
|
-
|
54
|
-
class Meta(SQLRecord.Meta, TracksRun.Meta, TracksUpdates.Meta):
|
55
|
-
abstract = False
|
56
|
-
app_label = "lamindb"
|
57
|
-
|
58
|
-
id: int = models.AutoField(primary_key=True)
|
59
|
-
"""Internal id, valid only in one DB instance."""
|
60
|
-
uid: str = CharField(
|
61
|
-
editable=False, unique=True, max_length=8, db_index=True, default=base62_8
|
62
|
-
)
|
63
|
-
"""Universal id, valid across DB instances."""
|
64
|
-
name: str = CharField(db_index=True)
|
65
|
-
"""Name of the person (forename(s) lastname)."""
|
66
|
-
email: str | None = EmailField(null=True, default=None)
|
67
|
-
"""Email of the person."""
|
68
|
-
external: bool = BooleanField(default=True, db_index=True)
|
69
|
-
"""Whether the person is external to the organization."""
|
70
|
-
records: Record = models.ManyToManyField(
|
71
|
-
Record, through="RecordPerson", related_name="linked_people"
|
72
|
-
)
|
73
|
-
"""Linked records."""
|
74
|
-
|
75
|
-
@overload
|
76
|
-
def __init__(
|
77
|
-
self,
|
78
|
-
name: str,
|
79
|
-
email: str | None = None,
|
80
|
-
external: bool = True,
|
81
|
-
): ...
|
82
|
-
|
83
|
-
@overload
|
84
|
-
def __init__(
|
85
|
-
self,
|
86
|
-
*db_args,
|
87
|
-
): ...
|
88
|
-
|
89
|
-
def __init__(self, *args, **kwargs):
|
90
|
-
super().__init__(*args, **kwargs)
|
37
|
+
from .block import ProjectBlock
|
91
38
|
|
92
39
|
|
93
40
|
class Reference(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
@@ -118,6 +65,8 @@ class Reference(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
|
118
65
|
"""Universal id, valid across DB instances."""
|
119
66
|
name: str = CharField(db_index=True)
|
120
67
|
"""Title or name of the reference document."""
|
68
|
+
description: str | None = TextField(null=True)
|
69
|
+
"""A description."""
|
121
70
|
type: Reference | None = ForeignKey(
|
122
71
|
"self", PROTECT, null=True, related_name="references"
|
123
72
|
)
|
@@ -150,30 +99,32 @@ class Reference(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
|
150
99
|
],
|
151
100
|
)
|
152
101
|
"""Digital Object Identifier (DOI) for the reference."""
|
153
|
-
description: str | None = CharField(null=True, db_index=True)
|
154
|
-
"""Description of the reference."""
|
155
102
|
text: str | None = TextField(null=True, db_index=True)
|
156
103
|
"""Abstract or full text of the reference to make it searchable."""
|
157
104
|
date: DateType | None = DateField(null=True, default=None)
|
158
105
|
"""Date of creation or publication of the reference."""
|
159
|
-
authors: Person = models.ManyToManyField(Person, related_name="references")
|
160
|
-
"""All people associated with this reference."""
|
161
106
|
artifacts: Artifact = models.ManyToManyField(
|
162
107
|
Artifact, through="ArtifactReference", related_name="references"
|
163
108
|
)
|
164
|
-
"""
|
109
|
+
"""Annotated artifacts."""
|
165
110
|
transforms: Artifact = models.ManyToManyField(
|
166
111
|
Transform, through="TransformReference", related_name="references"
|
167
112
|
)
|
168
|
-
"""
|
113
|
+
"""Annotated transforms."""
|
169
114
|
collections: Artifact = models.ManyToManyField(
|
170
115
|
Collection, through="CollectionReference", related_name="references"
|
171
116
|
)
|
172
|
-
"""
|
173
|
-
|
117
|
+
"""Annotated collections."""
|
118
|
+
linked_in_records: Record = models.ManyToManyField(
|
174
119
|
Record, through="RecordReference", related_name="linked_references"
|
175
120
|
)
|
176
|
-
"""Linked records."""
|
121
|
+
"""Linked in records."""
|
122
|
+
records: Record = models.ManyToManyField(
|
123
|
+
Record, through="ReferenceRecord", related_name="references"
|
124
|
+
)
|
125
|
+
"""Annotated records."""
|
126
|
+
projects: Project
|
127
|
+
"""Projects that annotate this reference."""
|
177
128
|
|
178
129
|
@overload
|
179
130
|
def __init__(
|
@@ -227,6 +178,8 @@ class Project(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
|
227
178
|
"""Universal id, valid across DB instances."""
|
228
179
|
name: str = CharField(db_index=True)
|
229
180
|
"""Title or name of the Project."""
|
181
|
+
description: str | None = TextField(null=True)
|
182
|
+
"""A description."""
|
230
183
|
type: Project | None = ForeignKey(
|
231
184
|
"self", PROTECT, null=True, related_name="projects"
|
232
185
|
)
|
@@ -261,50 +214,48 @@ class Project(SQLRecord, CanCurate, TracksRun, TracksUpdates, ValidateFields):
|
|
261
214
|
|
262
215
|
Reverse accessor for `.predecessors`.
|
263
216
|
"""
|
264
|
-
people: Person = models.ManyToManyField(
|
265
|
-
Person, through="PersonProject", related_name="projects"
|
266
|
-
)
|
267
|
-
"""Linked people."""
|
268
217
|
artifacts: Artifact = models.ManyToManyField(
|
269
218
|
Artifact, through="ArtifactProject", related_name="projects"
|
270
219
|
)
|
271
|
-
"""
|
220
|
+
"""Annotated artifacts."""
|
272
221
|
transforms: Transform = models.ManyToManyField(
|
273
222
|
Transform, through="TransformProject", related_name="projects"
|
274
223
|
)
|
275
|
-
"""
|
224
|
+
"""Annotated transforms."""
|
276
225
|
runs: Run = models.ManyToManyField(
|
277
226
|
Run, through="RunProject", related_name="projects"
|
278
227
|
)
|
279
|
-
"""
|
228
|
+
"""Annotated runs."""
|
280
229
|
ulabels: ULabel = models.ManyToManyField(
|
281
230
|
ULabel, through="ULabelProject", related_name="projects"
|
282
231
|
)
|
283
|
-
"""
|
232
|
+
"""Annotated ulabels."""
|
284
233
|
features: ULabel = models.ManyToManyField(
|
285
234
|
Feature, through="FeatureProject", related_name="projects"
|
286
235
|
)
|
287
|
-
"""
|
236
|
+
"""Annotated features."""
|
288
237
|
schemas: ULabel = models.ManyToManyField(
|
289
238
|
Schema, through="SchemaProject", related_name="projects"
|
290
239
|
)
|
291
|
-
"""
|
240
|
+
"""Annotated schemas."""
|
292
241
|
linked_in_records: Record = models.ManyToManyField(
|
293
242
|
Record, through="RecordProject", related_name="linked_projects"
|
294
243
|
)
|
295
|
-
"""Linked records."""
|
244
|
+
"""Linked in records."""
|
296
245
|
records: Record = models.ManyToManyField(
|
297
246
|
Record, through="ProjectRecord", related_name="projects"
|
298
247
|
)
|
299
|
-
"""Annotated
|
248
|
+
"""Annotated records."""
|
300
249
|
collections: Collection = models.ManyToManyField(
|
301
250
|
Collection, through="CollectionProject", related_name="projects"
|
302
251
|
)
|
303
|
-
"""
|
252
|
+
"""Annotated collections."""
|
304
253
|
references: Reference = models.ManyToManyField("Reference", related_name="projects")
|
305
|
-
"""
|
254
|
+
"""Annotated references."""
|
306
255
|
_status_code: int = models.SmallIntegerField(default=0, db_index=True)
|
307
256
|
"""Status code."""
|
257
|
+
blocks: ProjectBlock
|
258
|
+
"""Blocks that annotate this project."""
|
308
259
|
|
309
260
|
@overload
|
310
261
|
def __init__(
|
@@ -402,17 +353,6 @@ class ULabelProject(BaseSQLRecord, IsLink, TracksRun):
|
|
402
353
|
unique_together = ("ulabel", "project")
|
403
354
|
|
404
355
|
|
405
|
-
class PersonProject(BaseSQLRecord, IsLink, TracksRun):
|
406
|
-
id: int = models.BigAutoField(primary_key=True)
|
407
|
-
person: Person = ForeignKey(Person, CASCADE, related_name="links_project")
|
408
|
-
project: Project = ForeignKey(Project, PROTECT, related_name="links_person")
|
409
|
-
role: str | None = CharField(null=True, default=None)
|
410
|
-
|
411
|
-
class Meta:
|
412
|
-
app_label = "lamindb"
|
413
|
-
unique_together = ("person", "project")
|
414
|
-
|
415
|
-
|
416
356
|
class FeatureProject(BaseSQLRecord, IsLink, TracksRun):
|
417
357
|
id: int = models.BigAutoField(primary_key=True)
|
418
358
|
feature: Feature = ForeignKey(Feature, CASCADE, related_name="links_project")
|
@@ -433,15 +373,22 @@ class SchemaProject(BaseSQLRecord, IsLink, TracksRun):
|
|
433
373
|
unique_together = ("schema", "project")
|
434
374
|
|
435
375
|
|
436
|
-
|
376
|
+
# for annotation of records with references, RecordReference is for storing reference values
|
377
|
+
class ReferenceRecord(BaseSQLRecord, IsLink, TracksRun):
|
437
378
|
id: int = models.BigAutoField(primary_key=True)
|
438
|
-
|
439
|
-
feature: Feature = ForeignKey(
|
440
|
-
|
379
|
+
reference: Reference = ForeignKey(Reference, PROTECT, related_name="links_record")
|
380
|
+
feature: Feature | None = ForeignKey(
|
381
|
+
Feature,
|
382
|
+
PROTECT,
|
383
|
+
null=True,
|
384
|
+
default=None,
|
385
|
+
related_name="links_referencerecord",
|
386
|
+
)
|
387
|
+
record: Record = ForeignKey(Record, CASCADE, related_name="links_reference")
|
441
388
|
|
442
389
|
class Meta:
|
443
390
|
app_label = "lamindb"
|
444
|
-
unique_together = ("
|
391
|
+
unique_together = ("reference", "feature", "record")
|
445
392
|
|
446
393
|
|
447
394
|
class RecordReference(BaseSQLRecord, IsLink):
|
@@ -450,7 +397,7 @@ class RecordReference(BaseSQLRecord, IsLink):
|
|
450
397
|
feature: Feature = ForeignKey(
|
451
398
|
Feature, PROTECT, related_name="links_recordreference"
|
452
399
|
)
|
453
|
-
value: Reference = ForeignKey(Reference, PROTECT, related_name="
|
400
|
+
value: Reference = ForeignKey(Reference, PROTECT, related_name="links_in_record")
|
454
401
|
|
455
402
|
class Meta:
|
456
403
|
app_label = "lamindb"
|
@@ -460,7 +407,6 @@ class RecordReference(BaseSQLRecord, IsLink):
|
|
460
407
|
# for annotation of records with projects, RecordProject is for storing project values
|
461
408
|
class ProjectRecord(BaseSQLRecord, IsLink, TracksRun):
|
462
409
|
id: int = models.BigAutoField(primary_key=True)
|
463
|
-
record: Record = ForeignKey(Record, CASCADE, related_name="links_project")
|
464
410
|
project: Project = ForeignKey(Project, PROTECT, related_name="links_record")
|
465
411
|
feature: Feature | None = ForeignKey(
|
466
412
|
Feature,
|
@@ -469,11 +415,11 @@ class ProjectRecord(BaseSQLRecord, IsLink, TracksRun):
|
|
469
415
|
default=None,
|
470
416
|
related_name="links_projectrecord",
|
471
417
|
)
|
418
|
+
record: Record = ForeignKey(Record, CASCADE, related_name="links_project")
|
472
419
|
|
473
420
|
class Meta:
|
474
|
-
# can have the same label linked to the same artifact if the feature is different
|
475
421
|
app_label = "lamindb"
|
476
|
-
unique_together = ("
|
422
|
+
unique_together = ("project", "feature", "record")
|
477
423
|
|
478
424
|
|
479
425
|
class RecordProject(BaseSQLRecord, IsLink):
|
@@ -503,7 +449,6 @@ class ArtifactReference(BaseSQLRecord, IsLink, TracksRun):
|
|
503
449
|
|
504
450
|
class Meta:
|
505
451
|
app_label = "lamindb"
|
506
|
-
# can have the same label linked to the same artifact if the feature is different
|
507
452
|
unique_together = ("artifact", "reference", "feature")
|
508
453
|
|
509
454
|
|
lamindb/models/query_manager.py
CHANGED
@@ -302,7 +302,7 @@ class QueryManager(Manager):
|
|
302
302
|
def all(self):
|
303
303
|
"""Return QuerySet of all.
|
304
304
|
|
305
|
-
For `**kwargs`, see :meth:`lamindb.models.QuerySet.
|
305
|
+
For `**kwargs`, see :meth:`lamindb.models.QuerySet.to_dataframe`.
|
306
306
|
"""
|
307
307
|
self._track_run_input_manager()
|
308
308
|
return super().all()
|