lamindb 0.74.2__py3-none-any.whl → 0.75.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 +1 -1
- lamindb/_artifact.py +85 -43
- lamindb/_can_validate.py +55 -20
- lamindb/_collection.py +36 -28
- lamindb/_curate.py +55 -44
- lamindb/_feature_set.py +5 -5
- lamindb/_filter.py +3 -3
- lamindb/_finish.py +29 -23
- lamindb/_from_values.py +41 -60
- lamindb/_is_versioned.py +1 -1
- lamindb/_parents.py +38 -13
- lamindb/_record.py +22 -36
- lamindb/_save.py +6 -24
- lamindb/_transform.py +27 -16
- lamindb/core/_data.py +14 -16
- lamindb/core/_feature_manager.py +38 -53
- lamindb/core/_label_manager.py +26 -34
- lamindb/core/_mapped_collection.py +1 -1
- lamindb/core/_run_context.py +6 -8
- lamindb/core/datasets/_core.py +7 -13
- lamindb/core/exceptions.py +11 -0
- lamindb/core/storage/__init__.py +1 -0
- lamindb/core/storage/_anndata_accessor.py +735 -0
- lamindb/core/storage/_backed_access.py +77 -747
- lamindb/core/storage/paths.py +9 -14
- lamindb/core/types.py +3 -0
- lamindb/core/versioning.py +1 -1
- lamindb/integrations/__init__.py +1 -0
- {lamindb-0.74.2.dist-info → lamindb-0.75.0.dist-info}/METADATA +6 -6
- lamindb-0.75.0.dist-info/RECORD +58 -0
- lamindb-0.74.2.dist-info/RECORD +0 -57
- {lamindb-0.74.2.dist-info → lamindb-0.75.0.dist-info}/LICENSE +0 -0
- {lamindb-0.74.2.dist-info → lamindb-0.75.0.dist-info}/WHEEL +0 -0
lamindb/core/_feature_manager.py
CHANGED
@@ -39,7 +39,7 @@ from lamindb._feature import FEATURE_TYPES, convert_numpy_dtype_to_lamin_feature
|
|
39
39
|
from lamindb._feature_set import DICT_KEYS_TYPE, FeatureSet
|
40
40
|
from lamindb._record import (
|
41
41
|
REGISTRY_UNIQUE_FIELD,
|
42
|
-
|
42
|
+
get_name_field,
|
43
43
|
transfer_fk_to_default_db_bulk,
|
44
44
|
transfer_to_default_db,
|
45
45
|
)
|
@@ -88,12 +88,12 @@ def get_feature_set_by_slot_(host) -> dict:
|
|
88
88
|
host_id_field = get_host_id_field(host)
|
89
89
|
kwargs = {host_id_field: host.id}
|
90
90
|
# otherwise, we need a query
|
91
|
-
|
91
|
+
links_feature_set = (
|
92
92
|
host.feature_sets.through.objects.using(host_db)
|
93
93
|
.filter(**kwargs)
|
94
94
|
.select_related("featureset")
|
95
95
|
)
|
96
|
-
return {fsl.slot: fsl.featureset for fsl in
|
96
|
+
return {fsl.slot: fsl.featureset for fsl in links_feature_set}
|
97
97
|
|
98
98
|
|
99
99
|
def get_label_links(
|
@@ -112,8 +112,8 @@ def get_label_links(
|
|
112
112
|
def get_feature_set_links(host: Artifact | Collection) -> QuerySet:
|
113
113
|
host_id_field = get_host_id_field(host)
|
114
114
|
kwargs = {host_id_field: host.id}
|
115
|
-
|
116
|
-
return
|
115
|
+
links_feature_set = host.feature_sets.through.objects.filter(**kwargs)
|
116
|
+
return links_feature_set
|
117
117
|
|
118
118
|
|
119
119
|
def get_link_attr(link: LinkORM | type[LinkORM], data: HasFeatures) -> str:
|
@@ -122,12 +122,7 @@ def get_link_attr(link: LinkORM | type[LinkORM], data: HasFeatures) -> str:
|
|
122
122
|
link_model_name == "ModelBase" or link_model_name == "RecordMeta"
|
123
123
|
): # we passed the type of the link
|
124
124
|
link_model_name = link.__name__
|
125
|
-
|
126
|
-
if link_attr == "ExperimentalFactor":
|
127
|
-
link_attr = "experimental_factor"
|
128
|
-
else:
|
129
|
-
link_attr = link_attr.lower()
|
130
|
-
return link_attr
|
125
|
+
return link_model_name.replace(data.__class__.__name__, "").lower()
|
131
126
|
|
132
127
|
|
133
128
|
# Custom aggregation for SQLite
|
@@ -182,14 +177,14 @@ def print_features(
|
|
182
177
|
non_labels_msg = ""
|
183
178
|
if self.id is not None and self.__class__ == Artifact or self.__class__ == Run:
|
184
179
|
attr_name = "param" if print_params else "feature"
|
185
|
-
|
186
|
-
getattr(self, f"{attr_name}_values")
|
180
|
+
_feature_values = (
|
181
|
+
getattr(self, f"_{attr_name}_values")
|
187
182
|
.values(f"{attr_name}__name", f"{attr_name}__dtype")
|
188
183
|
.annotate(values=custom_aggregate("value", self._state.db))
|
189
184
|
.order_by(f"{attr_name}__name")
|
190
185
|
)
|
191
|
-
if len(
|
192
|
-
for fv in
|
186
|
+
if len(_feature_values) > 0:
|
187
|
+
for fv in _feature_values:
|
193
188
|
feature_name = fv[f"{attr_name}__name"]
|
194
189
|
feature_dtype = fv[f"{attr_name}__dtype"]
|
195
190
|
values = fv["values"]
|
@@ -217,7 +212,7 @@ def print_features(
|
|
217
212
|
for slot, feature_set in get_feature_set_by_slot_(self).items():
|
218
213
|
features = feature_set.members
|
219
214
|
# features.first() is a lot slower than features[0] here
|
220
|
-
name_field =
|
215
|
+
name_field = get_name_field(features[0])
|
221
216
|
feature_names = list(features.values_list(name_field, flat=True)[:20])
|
222
217
|
type_str = f": {feature_set.registry}" if print_types else ""
|
223
218
|
feature_set_msg += (
|
@@ -246,7 +241,7 @@ def parse_feature_sets_from_anndata(
|
|
246
241
|
from lamindb.core.storage._backed_access import backed_access
|
247
242
|
|
248
243
|
using_key = settings._using_key
|
249
|
-
data_parse = backed_access(filepath, using_key)
|
244
|
+
data_parse = backed_access(filepath, using_key=using_key)
|
250
245
|
else:
|
251
246
|
data_parse = ad.read_h5ad(filepath, backed="r")
|
252
247
|
type = "float"
|
@@ -316,13 +311,13 @@ def infer_feature_type_convert_json(
|
|
316
311
|
if len(value) > 0: # type: ignore
|
317
312
|
first_element_type = type(next(iter(value)))
|
318
313
|
if all(isinstance(elem, first_element_type) for elem in value):
|
319
|
-
if first_element_type
|
314
|
+
if first_element_type is bool:
|
320
315
|
return f"list[{FEATURE_TYPES['bool']}]", value
|
321
|
-
elif first_element_type
|
316
|
+
elif first_element_type is int:
|
322
317
|
return f"list[{FEATURE_TYPES['int']}]", value
|
323
|
-
elif first_element_type
|
318
|
+
elif first_element_type is float:
|
324
319
|
return f"list[{FEATURE_TYPES['float']}]", value
|
325
|
-
elif first_element_type
|
320
|
+
elif first_element_type is str:
|
326
321
|
if str_as_ulabel:
|
327
322
|
return FEATURE_TYPES["str"] + "[ULabel]", value
|
328
323
|
else:
|
@@ -390,7 +385,7 @@ def filter(cls, **expression) -> QuerySet:
|
|
390
385
|
feature = features.get(name=normalized_key)
|
391
386
|
if not feature.dtype.startswith("cat"):
|
392
387
|
feature_value = value_model.filter(feature=feature, value=value).one()
|
393
|
-
new_expression["
|
388
|
+
new_expression["_feature_values"] = feature_value
|
394
389
|
else:
|
395
390
|
if isinstance(value, str):
|
396
391
|
label = ULabel.filter(name=value).one()
|
@@ -478,7 +473,7 @@ def _add_values(
|
|
478
473
|
)
|
479
474
|
# figure out which of the values go where
|
480
475
|
features_labels = defaultdict(list)
|
481
|
-
|
476
|
+
_feature_values = []
|
482
477
|
not_validated_values = []
|
483
478
|
for key, value in features_values.items():
|
484
479
|
feature = model.filter(name=key).one()
|
@@ -508,7 +503,7 @@ def _add_values(
|
|
508
503
|
feature_value = value_model.filter(**filter_kwargs).one_or_none()
|
509
504
|
if feature_value is None:
|
510
505
|
feature_value = value_model(**filter_kwargs)
|
511
|
-
|
506
|
+
_feature_values.append(feature_value)
|
512
507
|
else:
|
513
508
|
if isinstance(value, Record) or (
|
514
509
|
isinstance(value, Iterable) and isinstance(next(iter(value)), Record)
|
@@ -578,7 +573,7 @@ def _add_values(
|
|
578
573
|
except Exception:
|
579
574
|
save(links, ignore_conflicts=True)
|
580
575
|
# now deal with links that were previously saved without a feature_id
|
581
|
-
|
576
|
+
links_saved = LinkORM.filter(
|
582
577
|
**{
|
583
578
|
"artifact_id": self._host.id,
|
584
579
|
f"{field_name}__in": [
|
@@ -586,7 +581,7 @@ def _add_values(
|
|
586
581
|
],
|
587
582
|
}
|
588
583
|
)
|
589
|
-
for link in
|
584
|
+
for link in links_saved.all():
|
590
585
|
# TODO: also check for inconsistent features
|
591
586
|
if link.feature_id is None:
|
592
587
|
link.feature_id = [
|
@@ -595,13 +590,13 @@ def _add_values(
|
|
595
590
|
if l.id == getattr(link, field_name)
|
596
591
|
][0]
|
597
592
|
link.save()
|
598
|
-
if
|
599
|
-
save(
|
593
|
+
if _feature_values:
|
594
|
+
save(_feature_values)
|
600
595
|
if is_param:
|
601
|
-
LinkORM = self._host.
|
596
|
+
LinkORM = self._host._param_values.through
|
602
597
|
valuefield_id = "paramvalue_id"
|
603
598
|
else:
|
604
|
-
LinkORM = self._host.
|
599
|
+
LinkORM = self._host._feature_values.through
|
605
600
|
valuefield_id = "featurevalue_id"
|
606
601
|
links = [
|
607
602
|
LinkORM(
|
@@ -610,7 +605,7 @@ def _add_values(
|
|
610
605
|
valuefield_id: feature_value.id,
|
611
606
|
}
|
612
607
|
)
|
613
|
-
for feature_value in
|
608
|
+
for feature_value in _feature_values
|
614
609
|
]
|
615
610
|
# a link might already exist, to avoid raising a unique constraint
|
616
611
|
# error, ignore_conflicts
|
@@ -683,10 +678,10 @@ def _add_set_from_df(
|
|
683
678
|
):
|
684
679
|
"""Add feature set corresponding to column names of DataFrame."""
|
685
680
|
if isinstance(self._host, Artifact):
|
686
|
-
assert self._host.
|
681
|
+
assert self._host._accessor == "DataFrame" # noqa: S101
|
687
682
|
else:
|
688
683
|
# Collection
|
689
|
-
assert self._host.artifact.
|
684
|
+
assert self._host.artifact._accessor == "DataFrame" # noqa: S101
|
690
685
|
|
691
686
|
# parse and register features
|
692
687
|
registry = field.field.model
|
@@ -714,7 +709,7 @@ def _add_set_from_anndata(
|
|
714
709
|
):
|
715
710
|
"""Add features from AnnData."""
|
716
711
|
if isinstance(self._host, Artifact):
|
717
|
-
assert self._host.
|
712
|
+
assert self._host._accessor == "AnnData" # noqa: S101
|
718
713
|
else:
|
719
714
|
raise NotImplementedError()
|
720
715
|
|
@@ -744,7 +739,7 @@ def _add_set_from_mudata(
|
|
744
739
|
if obs_fields is None:
|
745
740
|
obs_fields = {}
|
746
741
|
if isinstance(self._host, Artifact):
|
747
|
-
assert self._host.
|
742
|
+
assert self._host._accessor == "MuData" # noqa: S101
|
748
743
|
else:
|
749
744
|
raise NotImplementedError()
|
750
745
|
|
@@ -770,7 +765,7 @@ def _add_set_from_mudata(
|
|
770
765
|
self._host.save()
|
771
766
|
|
772
767
|
|
773
|
-
def _add_from(self, data: HasFeatures
|
768
|
+
def _add_from(self, data: HasFeatures):
|
774
769
|
"""Transfer features from a artifact or collection."""
|
775
770
|
# This only covers feature sets, though.
|
776
771
|
using_key = settings._using_key
|
@@ -781,24 +776,14 @@ def _add_from(self, data: HasFeatures, parents: bool = True):
|
|
781
776
|
registry = members[0].__class__
|
782
777
|
# note here the features are transferred based on an unique field
|
783
778
|
field = REGISTRY_UNIQUE_FIELD.get(registry.__name__.lower(), "uid")
|
784
|
-
|
785
|
-
|
786
|
-
field = "ontology_id"
|
787
|
-
elif hasattr(registry, "ensembl_gene_id"):
|
788
|
-
field = "ensembl_gene_id"
|
789
|
-
elif hasattr(registry, "uniprotkb_id"):
|
790
|
-
field = "uniprotkb_id"
|
791
|
-
|
792
|
-
if registry.__get_name_with_schema__() == "bionty.Organism":
|
793
|
-
parents = False
|
779
|
+
if hasattr(registry, "_ontology_id_field"):
|
780
|
+
field = registry._ontology_id_field
|
794
781
|
# this will be e.g. be a list of ontology_ids or uids
|
795
782
|
member_uids = list(members.values_list(field, flat=True))
|
796
|
-
# create records from ontology_id
|
797
|
-
if
|
783
|
+
# create records from ontology_id
|
784
|
+
if hasattr(registry, "_ontology_id_field") and len(member_uids) > 0:
|
798
785
|
# create from bionty
|
799
|
-
|
800
|
-
if len(records) > 0:
|
801
|
-
save(records, parents=parents)
|
786
|
+
save(registry.from_values(member_uids, field=field))
|
802
787
|
validated = registry.validate(member_uids, field=field, mute=True)
|
803
788
|
new_members_uids = list(compress(member_uids, ~validated))
|
804
789
|
new_members = members.filter(**{f"{field}__in": new_members_uids}).all()
|
@@ -814,14 +799,14 @@ def _add_from(self, data: HasFeatures, parents: bool = True):
|
|
814
799
|
# in the previous step transfer_fk_to_default_db_bulk
|
815
800
|
transfer_to_default_db(feature, using_key, mute=mute, transfer_fk=False)
|
816
801
|
logger.info(f"saving {n_new_members} new {registry.__name__} records")
|
817
|
-
save(new_members
|
802
|
+
save(new_members)
|
818
803
|
|
819
804
|
# create a new feature set from feature values using the same uid
|
820
805
|
feature_set_self = FeatureSet.from_values(
|
821
806
|
member_uids, field=getattr(registry, field)
|
822
807
|
)
|
823
808
|
if feature_set_self is None:
|
824
|
-
if hasattr(registry, "
|
809
|
+
if hasattr(registry, "organism_id"):
|
825
810
|
logger.warning(
|
826
811
|
f"FeatureSet is not transferred, check if organism is set correctly: {feature_set}"
|
827
812
|
)
|
lamindb/core/_label_manager.py
CHANGED
@@ -4,13 +4,13 @@ from collections import defaultdict
|
|
4
4
|
from typing import TYPE_CHECKING, Dict
|
5
5
|
|
6
6
|
import numpy as np
|
7
|
-
from lamin_utils import colors
|
7
|
+
from lamin_utils import colors
|
8
8
|
from lnschema_core.models import Feature
|
9
9
|
|
10
10
|
from lamindb._from_values import _print_values
|
11
11
|
from lamindb._record import (
|
12
12
|
REGISTRY_UNIQUE_FIELD,
|
13
|
-
|
13
|
+
get_name_field,
|
14
14
|
transfer_fk_to_default_db_bulk,
|
15
15
|
transfer_to_default_db,
|
16
16
|
)
|
@@ -28,17 +28,19 @@ if TYPE_CHECKING:
|
|
28
28
|
def get_labels_as_dict(self: HasFeatures, links: bool = False):
|
29
29
|
exclude_set = {
|
30
30
|
"feature_sets",
|
31
|
-
"
|
32
|
-
"
|
31
|
+
"artifacts",
|
32
|
+
"input_of_runs",
|
33
33
|
"collections",
|
34
|
-
"
|
34
|
+
"_source_code_artifact_of",
|
35
35
|
"report_of",
|
36
36
|
"environment_of",
|
37
|
-
"
|
38
|
-
"
|
39
|
-
"
|
37
|
+
"links_collection",
|
38
|
+
"links_artifact",
|
39
|
+
"links_feature_set",
|
40
40
|
"previous_runs",
|
41
|
-
"
|
41
|
+
"_feature_values",
|
42
|
+
"_lnschema_core_collection__actions_+",
|
43
|
+
"_actions",
|
42
44
|
}
|
43
45
|
labels = {} # type: ignore
|
44
46
|
if self.id is None:
|
@@ -62,7 +64,7 @@ def print_labels(self: HasFeatures, field: str = "name", print_types: bool = Fal
|
|
62
64
|
try:
|
63
65
|
labels_list = list(labels.values_list(field, flat=True))
|
64
66
|
if len(labels_list) > 0:
|
65
|
-
|
67
|
+
get_name_field(labels)
|
66
68
|
print_values = _print_values(labels_list, n=10)
|
67
69
|
type_str = f": {related_model}" if print_types else ""
|
68
70
|
labels_msg += f" .{related_name}{type_str} = {print_values}\n"
|
@@ -76,32 +78,24 @@ def print_labels(self: HasFeatures, field: str = "name", print_types: bool = Fal
|
|
76
78
|
|
77
79
|
|
78
80
|
# Alex: is this a label transfer function?
|
79
|
-
def validate_labels(labels: QuerySet | list | dict
|
81
|
+
def validate_labels(labels: QuerySet | list | dict):
|
80
82
|
def validate_labels_registry(
|
81
|
-
labels: QuerySet | list | dict,
|
83
|
+
labels: QuerySet | list | dict,
|
82
84
|
) -> tuple[list[str], list[str]]:
|
83
85
|
if len(labels) == 0:
|
84
86
|
return [], []
|
85
87
|
registry = labels[0].__class__
|
86
88
|
field = REGISTRY_UNIQUE_FIELD.get(registry.__name__.lower(), "uid")
|
87
|
-
if hasattr(registry, "
|
88
|
-
field =
|
89
|
-
elif hasattr(registry, "ensembl_gene_id"):
|
90
|
-
field = "ensembl_gene_id"
|
91
|
-
elif hasattr(registry, "uniprotkb_id"):
|
92
|
-
field = "uniprotkb_id"
|
93
|
-
if registry.__get_name_with_schema__() == "bionty.Organism":
|
94
|
-
parents = False
|
89
|
+
if hasattr(registry, "_ontology_id_field"):
|
90
|
+
field = registry._ontology_id_field
|
95
91
|
# if the field value is None, use uid field
|
96
92
|
label_uids = np.array(
|
97
93
|
[getattr(label, field) for label in labels if label is not None]
|
98
94
|
)
|
99
|
-
# save labels from ontology_ids
|
100
|
-
if
|
95
|
+
# save labels from ontology_ids
|
96
|
+
if hasattr(registry, "_ontology_id_field") and len(label_uids) > 0:
|
101
97
|
try:
|
102
|
-
|
103
|
-
if len(records) > 0:
|
104
|
-
save(records, parents=parents)
|
98
|
+
save(registry.from_values(label_uids, field=field))
|
105
99
|
except Exception: # noqa S110
|
106
100
|
pass
|
107
101
|
field = "uid"
|
@@ -117,11 +111,9 @@ def validate_labels(labels: QuerySet | list | dict, parents: bool = True):
|
|
117
111
|
if isinstance(labels, Dict):
|
118
112
|
result = {}
|
119
113
|
for registry, labels_registry in labels.items():
|
120
|
-
result[registry] = validate_labels_registry(
|
121
|
-
labels_registry, parents=parents
|
122
|
-
)
|
114
|
+
result[registry] = validate_labels_registry(labels_registry)
|
123
115
|
else:
|
124
|
-
return validate_labels_registry(labels
|
116
|
+
return validate_labels_registry(labels)
|
125
117
|
|
126
118
|
|
127
119
|
class LabelManager:
|
@@ -176,7 +168,7 @@ class LabelManager:
|
|
176
168
|
|
177
169
|
return get_labels(self._host, feature=feature, mute=mute, flat_names=flat_names)
|
178
170
|
|
179
|
-
def add_from(self, data: HasFeatures
|
171
|
+
def add_from(self, data: HasFeatures) -> None:
|
180
172
|
"""Add labels from an artifact or collection to another artifact or collection.
|
181
173
|
|
182
174
|
Examples:
|
@@ -202,15 +194,15 @@ class LabelManager:
|
|
202
194
|
data_name_lower = data.__class__.__name__.lower()
|
203
195
|
labels_by_features = defaultdict(list)
|
204
196
|
features = set()
|
205
|
-
_, new_labels = validate_labels(labels
|
197
|
+
_, new_labels = validate_labels(labels)
|
206
198
|
if len(new_labels) > 0:
|
207
199
|
transfer_fk_to_default_db_bulk(new_labels, using_key)
|
208
200
|
for label in labels:
|
209
201
|
# if the link table doesn't follow this convention, we'll ignore it
|
210
|
-
if not hasattr(label, f"{data_name_lower}
|
202
|
+
if not hasattr(label, f"links_{data_name_lower}"):
|
211
203
|
key = None
|
212
204
|
else:
|
213
|
-
link = getattr(label, f"{data_name_lower}
|
205
|
+
link = getattr(label, f"links_{data_name_lower}").get(
|
214
206
|
**{f"{data_name_lower}_id": data.id}
|
215
207
|
)
|
216
208
|
if link.feature is not None:
|
@@ -237,7 +229,7 @@ class LabelManager:
|
|
237
229
|
transfer_to_default_db(
|
238
230
|
feature, using_key, mute=True, transfer_fk=False
|
239
231
|
)
|
240
|
-
save(new_features
|
232
|
+
save(new_features)
|
241
233
|
if hasattr(self._host, related_name):
|
242
234
|
for feature_name, labels in labels_by_features.items():
|
243
235
|
if feature_name is not None:
|
lamindb/core/_run_context.py
CHANGED
@@ -11,7 +11,6 @@ from lamin_utils import logger
|
|
11
11
|
from lamindb_setup.core.hashing import hash_file
|
12
12
|
from lnschema_core import Run, Transform, ids
|
13
13
|
from lnschema_core.models import Param, ParamValue, RunParamValue
|
14
|
-
from lnschema_core.types import TransformType
|
15
14
|
from lnschema_core.users import current_user_id
|
16
15
|
|
17
16
|
from ._settings import settings
|
@@ -27,6 +26,7 @@ from .versioning import bump_version as bump_version_function
|
|
27
26
|
|
28
27
|
if TYPE_CHECKING:
|
29
28
|
from lamindb_setup.core.types import UPathStr
|
29
|
+
from lnschema_core.types import TransformType
|
30
30
|
|
31
31
|
is_run_from_ipython = getattr(builtins, "__IPYTHON__", False)
|
32
32
|
|
@@ -279,14 +279,14 @@ class run_context:
|
|
279
279
|
).one_or_none()
|
280
280
|
if is_run_from_ipython:
|
281
281
|
key, name = cls._track_notebook(path=path)
|
282
|
-
transform_type =
|
282
|
+
transform_type = "notebook"
|
283
283
|
transform_ref = None
|
284
284
|
transform_ref_type = None
|
285
285
|
else:
|
286
286
|
(name, key, transform_ref, transform_ref_type) = cls._track_script(
|
287
287
|
path=path
|
288
288
|
)
|
289
|
-
transform_type =
|
289
|
+
transform_type = "script"
|
290
290
|
# overwrite whatever is auto-detected in the notebook or script
|
291
291
|
if transform_settings.name is not None:
|
292
292
|
name = transform_settings.name
|
@@ -323,9 +323,7 @@ class run_context:
|
|
323
323
|
cls.transform = transform_exists
|
324
324
|
|
325
325
|
if new_run is None: # for notebooks, default to loading latest runs
|
326
|
-
new_run =
|
327
|
-
False if cls.transform.type == TransformType.notebook.value else True
|
328
|
-
) # type: ignore
|
326
|
+
new_run = False if cls.transform.type == "notebook" else True # type: ignore
|
329
327
|
|
330
328
|
run = None
|
331
329
|
from lamindb._run import Run
|
@@ -479,7 +477,7 @@ class run_context:
|
|
479
477
|
transform.save()
|
480
478
|
logger.important(f"updated: {transform}")
|
481
479
|
# check whether transform source code was already saved
|
482
|
-
if transform.
|
480
|
+
if transform._source_code_artifact_id is not None:
|
483
481
|
response = None
|
484
482
|
if is_run_from_ipython:
|
485
483
|
if os.getenv("LAMIN_TESTING") is None:
|
@@ -491,7 +489,7 @@ class run_context:
|
|
491
489
|
response = "y"
|
492
490
|
else:
|
493
491
|
hash, _ = hash_file(cls.path) # ignore hash_type for now
|
494
|
-
if hash != transform.
|
492
|
+
if hash != transform._source_code_artifact.hash:
|
495
493
|
# only if hashes don't match, we need user input
|
496
494
|
if os.getenv("LAMIN_TESTING") is None:
|
497
495
|
response = input(
|
lamindb/core/datasets/_core.py
CHANGED
@@ -83,7 +83,7 @@ def file_tsv_rnaseq_nfcore_salmon_merged_gene_counts(
|
|
83
83
|
ln.settings.verbosity = "error"
|
84
84
|
ln.Feature(name="assay", dtype=[bt.ExperimentalFactor]).save()
|
85
85
|
ln.Feature(name="organism", dtype=[bt.Organism]).save()
|
86
|
-
bt.ExperimentalFactor.
|
86
|
+
bt.ExperimentalFactor.from_source(ontology_id="EFO:0008896").save()
|
87
87
|
ln.settings.verbosity = verbosity
|
88
88
|
|
89
89
|
return Path(filepath)
|
@@ -185,19 +185,17 @@ def anndata_mouse_sc_lymph_node(
|
|
185
185
|
|
186
186
|
verbosity = ln.settings.verbosity
|
187
187
|
ln.settings.verbosity = "error"
|
188
|
-
auto_save_parents = bt.settings.auto_save_parents
|
189
|
-
bt.settings.auto_save_parents = False
|
190
188
|
# strain
|
191
|
-
bt.ExperimentalFactor.
|
189
|
+
bt.ExperimentalFactor.from_source(ontology_id="EFO:0004472").save()
|
192
190
|
# developmental stage
|
193
|
-
bt.ExperimentalFactor.
|
191
|
+
bt.ExperimentalFactor.from_source(ontology_id="EFO:0001272").save()
|
194
192
|
# tissue
|
195
|
-
bt.Tissue.
|
193
|
+
bt.Tissue.from_source(ontology_id="UBERON:0001542").save()
|
196
194
|
# cell types
|
197
195
|
ln.save(bt.CellType.from_values(["CL:0000115", "CL:0000738"], "ontology_id"))
|
198
196
|
# assays
|
199
197
|
ln.Feature(name="assay", dtype=[bt.ExperimentalFactor]).save()
|
200
|
-
bt.ExperimentalFactor.
|
198
|
+
bt.ExperimentalFactor.from_source(ontology_id="EFO:0008913").save()
|
201
199
|
# genes
|
202
200
|
validated = bt.Gene.public(organism="mouse").validate(
|
203
201
|
adata.var.index, field="ensembl_gene_id"
|
@@ -215,7 +213,6 @@ def anndata_mouse_sc_lymph_node(
|
|
215
213
|
labels += [ln.ULabel(name=name) for name in adata.obs[col]]
|
216
214
|
ln.save(labels)
|
217
215
|
ln.settings.verbosity = verbosity
|
218
|
-
bt.settings.auto_save_parents = auto_save_parents
|
219
216
|
|
220
217
|
return adata
|
221
218
|
|
@@ -313,8 +310,6 @@ def anndata_human_immune_cells(
|
|
313
310
|
|
314
311
|
verbosity = ln.settings.verbosity
|
315
312
|
ln.settings.verbosity = "error"
|
316
|
-
auto_save_parents = bt.settings.auto_save_parents
|
317
|
-
bt.settings.auto_save_parents = False
|
318
313
|
ln.save(
|
319
314
|
bt.Gene.from_values(
|
320
315
|
adata.var.index, field="ensembl_gene_id", organism="human"
|
@@ -328,17 +323,16 @@ def anndata_human_immune_cells(
|
|
328
323
|
ln.Feature(name="tissue", dtype=[bt.Tissue]).save()
|
329
324
|
ln.Feature(name="organism", dtype=[bt.Organism]).save()
|
330
325
|
ln.Feature(name="donor", dtype=[ln.ULabel]).save()
|
331
|
-
bt.ExperimentalFactor.
|
326
|
+
bt.ExperimentalFactor.from_source(ontology_id="EFO:0008913").save()
|
332
327
|
ln.save([ln.ULabel(name=name) for name in adata.obs.donor.unique()])
|
333
328
|
ln.settings.verbosity = verbosity
|
334
|
-
bt.settings.auto_save_parents = auto_save_parents
|
335
329
|
return adata
|
336
330
|
|
337
331
|
|
338
332
|
def anndata_with_obs() -> ad.AnnData:
|
339
333
|
"""Create a mini anndata with cell_type, disease and tissue."""
|
340
334
|
import anndata as ad
|
341
|
-
import bionty_base
|
335
|
+
import bionty.base as bionty_base
|
342
336
|
|
343
337
|
celltypes = ["T cell", "hematopoietic stem cell", "hepatocyte", "my new cell type"]
|
344
338
|
celltype_ids = ["CL:0000084", "CL:0000037", "CL:0000182", ""]
|
lamindb/core/exceptions.py
CHANGED
@@ -10,6 +10,7 @@ The registry base class:
|
|
10
10
|
NoTitleError
|
11
11
|
MissingTransformSettings
|
12
12
|
UpdateTransformSettings
|
13
|
+
IntegrityError
|
13
14
|
|
14
15
|
"""
|
15
16
|
|
@@ -25,6 +26,16 @@ class ValidationError(SystemExit):
|
|
25
26
|
# -------------------------------------------------------------------------------------
|
26
27
|
|
27
28
|
|
29
|
+
class IntegrityError(Exception):
|
30
|
+
"""Integrity error.
|
31
|
+
|
32
|
+
For instance, it's not allowed to delete artifacts outside managed storage
|
33
|
+
locations.
|
34
|
+
"""
|
35
|
+
|
36
|
+
pass
|
37
|
+
|
38
|
+
|
28
39
|
class NotebookNotSavedError(Exception):
|
29
40
|
"""Notebook wasn't saved."""
|
30
41
|
|