lamindb 1.3.2__py3-none-any.whl → 1.4.0__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 +3 -3
- lamindb/core/_context.py +64 -69
- lamindb/core/datasets/_small.py +2 -2
- lamindb/curators/__init__.py +683 -893
- lamindb/models/__init__.py +8 -1
- lamindb/models/_feature_manager.py +23 -19
- lamindb/models/_from_values.py +1 -1
- lamindb/models/_is_versioned.py +5 -15
- lamindb/models/artifact.py +210 -111
- lamindb/models/can_curate.py +4 -1
- lamindb/models/collection.py +6 -4
- lamindb/models/feature.py +27 -30
- lamindb/models/has_parents.py +22 -7
- lamindb/models/project.py +2 -2
- lamindb/models/query_set.py +6 -35
- lamindb/models/record.py +164 -116
- lamindb/models/run.py +56 -2
- lamindb/models/save.py +1 -3
- lamindb/models/schema.py +277 -77
- lamindb/models/transform.py +4 -13
- {lamindb-1.3.2.dist-info → lamindb-1.4.0.dist-info}/METADATA +6 -5
- {lamindb-1.3.2.dist-info → lamindb-1.4.0.dist-info}/RECORD +24 -24
- {lamindb-1.3.2.dist-info → lamindb-1.4.0.dist-info}/LICENSE +0 -0
- {lamindb-1.3.2.dist-info → lamindb-1.4.0.dist-info}/WHEEL +0 -0
lamindb/models/__init__.py
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
FeatureValue
|
22
22
|
InspectResult
|
23
23
|
ValidateFields
|
24
|
+
SchemaOptionals
|
24
25
|
|
25
26
|
"""
|
26
27
|
|
@@ -75,5 +76,11 @@ from .project import (
|
|
75
76
|
)
|
76
77
|
from .record import Migration
|
77
78
|
from .run import RunParamValue
|
78
|
-
from .schema import
|
79
|
+
from .schema import (
|
80
|
+
SchemaFeature,
|
81
|
+
SchemaParam,
|
82
|
+
ArtifactSchema,
|
83
|
+
SchemaComponent,
|
84
|
+
SchemaOptionals,
|
85
|
+
)
|
79
86
|
from .ulabel import ArtifactULabel, TransformULabel, RunULabel, CollectionULabel
|
@@ -313,6 +313,9 @@ def describe_features(
|
|
313
313
|
fs_data = _get_schemas_postgres(self, related_data=related_data)
|
314
314
|
for fs_id, (slot, data) in fs_data.items():
|
315
315
|
for registry_str, feature_names in data.items():
|
316
|
+
# prevent projects show up as features
|
317
|
+
if registry_str == "Project":
|
318
|
+
continue
|
316
319
|
schema = Schema.objects.using(self._state.db).get(id=fs_id)
|
317
320
|
schema_data[slot] = (schema, feature_names)
|
318
321
|
for feature_name in feature_names:
|
@@ -446,8 +449,6 @@ def describe_features(
|
|
446
449
|
dataset_tree = tree.add(
|
447
450
|
Text.assemble(
|
448
451
|
("Dataset features", "bold bright_magenta"),
|
449
|
-
("/", "dim"),
|
450
|
-
(".feature_sets", "dim bold"),
|
451
452
|
)
|
452
453
|
)
|
453
454
|
for child in int_features_tree_children:
|
@@ -648,7 +649,7 @@ def __getitem__(self, slot) -> QuerySet:
|
|
648
649
|
return getattr(schema, self._accessor_by_registry[orm_name]).all()
|
649
650
|
|
650
651
|
|
651
|
-
def filter_base(cls, **expression):
|
652
|
+
def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
|
652
653
|
from .artifact import Artifact
|
653
654
|
|
654
655
|
if cls is FeatureManager:
|
@@ -658,11 +659,12 @@ def filter_base(cls, **expression):
|
|
658
659
|
model = Param
|
659
660
|
value_model = ParamValue
|
660
661
|
keys_normalized = [key.split("__")[0] for key in expression]
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
662
|
+
if not _skip_validation:
|
663
|
+
validated = model.validate(keys_normalized, field="name", mute=True)
|
664
|
+
if sum(validated) != len(keys_normalized):
|
665
|
+
raise ValidationError(
|
666
|
+
f"Some keys in the filter expression are not registered as features: {np.array(keys_normalized)[~validated]}"
|
667
|
+
)
|
666
668
|
new_expression = {}
|
667
669
|
features = model.filter(name__in=keys_normalized).all().distinct()
|
668
670
|
feature_param = "param" if model is Param else "feature"
|
@@ -719,31 +721,33 @@ def filter_base(cls, **expression):
|
|
719
721
|
# https://laminlabs.slack.com/archives/C04FPE8V01W/p1688328084810609
|
720
722
|
raise NotImplementedError
|
721
723
|
if cls == FeatureManager or cls == ParamManagerArtifact:
|
722
|
-
return Artifact.filter(**new_expression)
|
724
|
+
return Artifact.objects.filter(**new_expression)
|
723
725
|
elif cls == ParamManagerRun:
|
724
|
-
return Run.filter(**new_expression)
|
726
|
+
return Run.objects.filter(**new_expression)
|
725
727
|
|
726
728
|
|
727
729
|
@classmethod # type: ignore
|
730
|
+
@deprecated("the filter() registry classmethod")
|
728
731
|
def filter(cls, **expression) -> QuerySet:
|
729
732
|
"""Query artifacts by features."""
|
730
|
-
return filter_base(cls, **expression)
|
733
|
+
return filter_base(cls, _skip_validation=False, **expression)
|
731
734
|
|
732
735
|
|
733
736
|
@classmethod # type: ignore
|
737
|
+
@deprecated("the filter() registry classmethod")
|
734
738
|
def get(cls, **expression) -> Record:
|
735
739
|
"""Query a single artifact by feature."""
|
736
|
-
return filter_base(cls, **expression).one()
|
740
|
+
return filter_base(cls, _skip_validation=False, **expression).one()
|
737
741
|
|
738
742
|
|
739
743
|
@property # type: ignore
|
740
744
|
def slots(self) -> dict[str, Schema]:
|
741
745
|
"""Schema by slot.
|
742
746
|
|
743
|
-
Example
|
747
|
+
Example::
|
744
748
|
|
745
|
-
|
746
|
-
{'var': <Schema: var>, 'obs': <Schema: obs>}
|
749
|
+
artifact.features.slots
|
750
|
+
#> {'var': <Schema: var>, 'obs': <Schema: obs>}
|
747
751
|
"""
|
748
752
|
if self._slots is None:
|
749
753
|
self._slots = get_schema_by_slot_(self._host)
|
@@ -1096,7 +1100,7 @@ def _add_set_from_df(
|
|
1096
1100
|
):
|
1097
1101
|
"""Add feature set corresponding to column names of DataFrame."""
|
1098
1102
|
assert self._host.otype == "DataFrame" # noqa: S101
|
1099
|
-
df = self._host.load()
|
1103
|
+
df = self._host.load(is_run_input=False)
|
1100
1104
|
schema = Schema.from_df(
|
1101
1105
|
df=df,
|
1102
1106
|
field=field,
|
@@ -1119,7 +1123,7 @@ def _add_set_from_anndata(
|
|
1119
1123
|
assert self._host.otype == "AnnData" # noqa: S101
|
1120
1124
|
|
1121
1125
|
# parse and register features
|
1122
|
-
adata = self._host.load()
|
1126
|
+
adata = self._host.load(is_run_input=False)
|
1123
1127
|
feature_sets = parse_staged_feature_sets_from_anndata(
|
1124
1128
|
adata,
|
1125
1129
|
var_field=var_field,
|
@@ -1162,7 +1166,7 @@ def _add_set_from_mudata(
|
|
1162
1166
|
assert self._host.otype == "MuData" # noqa: S101
|
1163
1167
|
|
1164
1168
|
# parse and register features
|
1165
|
-
mdata = self._host.load()
|
1169
|
+
mdata = self._host.load(is_run_input=False)
|
1166
1170
|
feature_sets = {}
|
1167
1171
|
|
1168
1172
|
obs_features = Feature.from_values(mdata.obs.columns) # type: ignore
|
@@ -1198,7 +1202,7 @@ def _add_set_from_spatialdata(
|
|
1198
1202
|
assert self._host.otype == "SpatialData" # noqa: S101
|
1199
1203
|
|
1200
1204
|
# parse and register features
|
1201
|
-
sdata = self._host.load()
|
1205
|
+
sdata = self._host.load(is_run_input=False)
|
1202
1206
|
feature_sets = {}
|
1203
1207
|
|
1204
1208
|
# sample features
|
lamindb/models/_from_values.py
CHANGED
@@ -85,7 +85,7 @@ def _from_values(
|
|
85
85
|
print_values = colors.yellow(_format_values(unmapped_values))
|
86
86
|
n_nonval = colors.yellow(f"{len(unmapped_values)} non-validated")
|
87
87
|
if not mute:
|
88
|
-
logger.
|
88
|
+
logger.info(
|
89
89
|
f"{colors.red('did not create')} {registry.__name__} record{s} for "
|
90
90
|
f"{n_nonval} {colors.italic(f'{field.field.name}{s}')}: {print_values}" # type: ignore
|
91
91
|
)
|
lamindb/models/_is_versioned.py
CHANGED
@@ -73,11 +73,11 @@ class IsVersioned(models.Model):
|
|
73
73
|
>>> new_artifact = ln.Artifact(df2, revises=artifact).save()
|
74
74
|
>>> new_artifact.versions()
|
75
75
|
"""
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
return (
|
77
|
+
self.__class__.using(self._state.db)
|
78
|
+
.filter(uid__startswith=self.stem_uid)
|
79
|
+
.order_by("-created_at")
|
80
|
+
)
|
81
81
|
|
82
82
|
def _add_to_version_family(self, revises: IsVersioned, version: str | None = None):
|
83
83
|
"""Add current record to a version family.
|
@@ -101,16 +101,6 @@ class IsVersioned(models.Model):
|
|
101
101
|
logger.success(f"updated uid from {old_uid} to {new_uid}!")
|
102
102
|
|
103
103
|
|
104
|
-
def message_update_key_in_version_family(
|
105
|
-
*,
|
106
|
-
suid: str,
|
107
|
-
existing_key: str,
|
108
|
-
registry: str,
|
109
|
-
new_key: str,
|
110
|
-
) -> str:
|
111
|
-
return f'Or update key "{existing_key}" to "{new_key}" for all previous versions:\n\nln.{registry}.filter(uid__startswith="{suid}").update(key="{new_key}")\n'
|
112
|
-
|
113
|
-
|
114
104
|
def bump_version(
|
115
105
|
version: str,
|
116
106
|
bump_type: str = "minor",
|