lamindb 1.5.0__py3-none-any.whl → 1.5.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/core/_context.py +28 -15
- lamindb/core/storage/_tiledbsoma.py +29 -13
- lamindb/curators/core.py +33 -43
- lamindb/migrations/0093_alter_schemacomponent_unique_together.py +16 -0
- lamindb/models/_feature_manager.py +24 -8
- lamindb/models/artifact.py +10 -11
- lamindb/models/has_parents.py +67 -12
- lamindb/models/query_set.py +3 -2
- lamindb/models/record.py +3 -4
- lamindb/models/schema.py +23 -28
- {lamindb-1.5.0.dist-info → lamindb-1.5.2.dist-info}/METADATA +1 -1
- {lamindb-1.5.0.dist-info → lamindb-1.5.2.dist-info}/RECORD +15 -14
- {lamindb-1.5.0.dist-info → lamindb-1.5.2.dist-info}/LICENSE +0 -0
- {lamindb-1.5.0.dist-info → lamindb-1.5.2.dist-info}/WHEEL +0 -0
lamindb/__init__.py
CHANGED
lamindb/core/_context.py
CHANGED
@@ -259,8 +259,8 @@ class Context:
|
|
259
259
|
self,
|
260
260
|
transform: str | Transform | None = None,
|
261
261
|
*,
|
262
|
-
project: str | None = None,
|
263
|
-
space: str | None = None,
|
262
|
+
project: str | Project | None = None,
|
263
|
+
space: str | Space | None = None,
|
264
264
|
params: dict | None = None,
|
265
265
|
new_run: bool | None = None,
|
266
266
|
path: str | None = None,
|
@@ -273,9 +273,10 @@ class Context:
|
|
273
273
|
|
274
274
|
Args:
|
275
275
|
transform: A transform (stem) `uid` (or record). If `None`, auto-creates a `transform` with its `uid`.
|
276
|
-
project: A project `name` or `uid` for labeling entities created during the run.
|
277
|
-
space: A space `name` or `uid`
|
278
|
-
|
276
|
+
project: A project, its `name` or `uid` for labeling entities created during the run.
|
277
|
+
space: A restricted space, its `name` or `uid` for creating sensitive entities are created during the run.
|
278
|
+
The default is the common `"All"` space that every LaminDB instance has.
|
279
|
+
The `space` argument doesn't affect `Storage`, `ULabel`, `Feature`, `Schema`, `Param` and bionty entities as these provide structure that should typically be commonly accessible.
|
279
280
|
If you want to manually move entities to a different space, set the `.space` field (:doc:`docs:access`).
|
280
281
|
params: A dictionary of parameters to track for the run.
|
281
282
|
new_run: If `False`, loads the latest run of transform
|
@@ -309,20 +310,32 @@ class Context:
|
|
309
310
|
if project is None:
|
310
311
|
project = os.environ.get("LAMIN_CURRENT_PROJECT")
|
311
312
|
if project is not None:
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
if project_record is None:
|
316
|
-
raise InvalidArgument(
|
317
|
-
f"Project '{project}' not found, either create it with `ln.Project(name='...').save()` or fix typos."
|
313
|
+
if isinstance(project, Project):
|
314
|
+
assert project._state.adding is False, ( # noqa: S101
|
315
|
+
"Project must be saved before passing it to track()"
|
318
316
|
)
|
317
|
+
project_record = project
|
318
|
+
else:
|
319
|
+
project_record = Project.filter(
|
320
|
+
Q(name=project) | Q(uid=project)
|
321
|
+
).one_or_none()
|
322
|
+
if project_record is None:
|
323
|
+
raise InvalidArgument(
|
324
|
+
f"Project '{project}' not found, either create it with `ln.Project(name='...').save()` or fix typos."
|
325
|
+
)
|
319
326
|
self._project = project_record
|
320
327
|
if space is not None:
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
f"Space '{space}', please check on the hub UI whether you have the correct `uid` or `name`."
|
328
|
+
if isinstance(space, Space):
|
329
|
+
assert space._state.adding is False, ( # noqa: S101
|
330
|
+
"Space must be saved before passing it to track()"
|
325
331
|
)
|
332
|
+
space_record = space
|
333
|
+
else:
|
334
|
+
space_record = Space.filter(Q(name=space) | Q(uid=space)).one_or_none()
|
335
|
+
if space_record is None:
|
336
|
+
raise InvalidArgument(
|
337
|
+
f"Space '{space}', please check on the hub UI whether you have the correct `uid` or `name`."
|
338
|
+
)
|
326
339
|
self._space = space_record
|
327
340
|
self._logging_message_track = ""
|
328
341
|
self._logging_message_imports = ""
|
@@ -110,7 +110,7 @@ def save_tiledbsoma_experiment(
|
|
110
110
|
) -> Artifact:
|
111
111
|
"""Write `AnnData` to `tiledbsoma.Experiment`.
|
112
112
|
|
113
|
-
Reads `AnnData` objects, writes them to `tiledbsoma.Experiment`, creates & saves an
|
113
|
+
Reads `AnnData` objects, writes them to `tiledbsoma.Experiment`, creates & saves an :class:`~lamindb.Artifact`.
|
114
114
|
|
115
115
|
Populates a column `lamin_run_uid` column in `obs` with the current `run.uid`.
|
116
116
|
|
@@ -202,28 +202,44 @@ def save_tiledbsoma_experiment(
|
|
202
202
|
context=ctx,
|
203
203
|
)
|
204
204
|
|
205
|
+
prepare_experiment = False
|
205
206
|
resize_experiment = False
|
206
207
|
if registration_mapping is not None:
|
207
|
-
|
208
|
+
soma_version_parsed = version.parse(soma.__version__)
|
209
|
+
if soma_version_parsed < version.parse("1.15.0rc4"):
|
208
210
|
n_observations = len(registration_mapping.obs_axis.data)
|
209
211
|
else:
|
210
212
|
n_observations = registration_mapping.get_obs_shape()
|
211
|
-
|
213
|
+
prepare_experiment = soma_version_parsed >= version.parse("1.16.2")
|
214
|
+
resize_experiment = not prepare_experiment
|
212
215
|
else: # happens only if not appending and only one adata passed
|
213
216
|
assert len(adata_objects) == 1 # noqa: S101
|
214
217
|
n_observations = adata_objects[0].n_obs
|
215
218
|
|
216
219
|
logger.important(f"Writing the tiledbsoma store to {storepath_str}")
|
220
|
+
experiment_exists: bool | None = None
|
217
221
|
for adata_obj in adata_objects:
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
222
|
+
# do not recheck if True
|
223
|
+
if not experiment_exists and (resize_experiment or prepare_experiment):
|
224
|
+
experiment_exists = soma.Experiment.exists(storepath_str, context=ctx)
|
225
|
+
if experiment_exists:
|
226
|
+
# both can only happen if registration_mapping is not None
|
227
|
+
if resize_experiment:
|
228
|
+
soma_io.resize_experiment(
|
229
|
+
storepath_str,
|
230
|
+
nobs=n_observations,
|
231
|
+
nvars=registration_mapping.get_var_shapes(),
|
232
|
+
context=ctx,
|
233
|
+
)
|
234
|
+
resize_experiment = False
|
235
|
+
elif prepare_experiment:
|
236
|
+
registration_mapping.prepare_experiment(storepath_str, context=ctx)
|
237
|
+
prepare_experiment = False
|
238
|
+
registration_mapping_write = (
|
239
|
+
registration_mapping.subset_for_anndata(adata_obj)
|
240
|
+
if hasattr(registration_mapping, "subset_for_anndata")
|
241
|
+
else registration_mapping
|
242
|
+
)
|
227
243
|
soma_io.from_anndata(
|
228
244
|
storepath_str,
|
229
245
|
adata_obj,
|
@@ -231,7 +247,7 @@ def save_tiledbsoma_experiment(
|
|
231
247
|
context=ctx,
|
232
248
|
obs_id_name=obs_id_name,
|
233
249
|
var_id_name=var_id_name,
|
234
|
-
registration_mapping=
|
250
|
+
registration_mapping=registration_mapping_write,
|
235
251
|
**kwargs,
|
236
252
|
)
|
237
253
|
|
lamindb/curators/core.py
CHANGED
@@ -305,6 +305,8 @@ class SlotsCurator(Curator):
|
|
305
305
|
for slot, curator in self._slots.items():
|
306
306
|
logger.info(f"validating slot {slot} ...")
|
307
307
|
curator.validate()
|
308
|
+
# set _is_validated to True as no slot raised an error
|
309
|
+
self._is_validated = True
|
308
310
|
|
309
311
|
@doc_args(SAVE_ARTIFACT_DOCSTRING)
|
310
312
|
def save_artifact(
|
@@ -510,7 +512,7 @@ class DataFrameCurator(Curator):
|
|
510
512
|
categoricals=categoricals,
|
511
513
|
index=schema.index,
|
512
514
|
slot=slot,
|
513
|
-
|
515
|
+
maximal_set=schema.maximal_set,
|
514
516
|
)
|
515
517
|
|
516
518
|
@property
|
@@ -836,7 +838,7 @@ class SpatialDataCurator(SlotsCurator):
|
|
836
838
|
sub_slot = split_result[1]
|
837
839
|
data_object = self._dataset.attrs[split_result[1]]
|
838
840
|
data_object = pd.DataFrame([data_object])
|
839
|
-
self._slots[slot] = DataFrameCurator(data_object, slot_schema)
|
841
|
+
self._slots[slot] = DataFrameCurator(data_object, slot_schema, slot)
|
840
842
|
_assign_var_fields_categoricals_multimodal(
|
841
843
|
modality=table_key,
|
842
844
|
slot_type=sub_slot,
|
@@ -850,27 +852,20 @@ class SpatialDataCurator(SlotsCurator):
|
|
850
852
|
|
851
853
|
|
852
854
|
class CatVector:
|
853
|
-
"""
|
854
|
-
|
855
|
-
Args:
|
856
|
-
values_getter: A callable or iterable that returns the values to validate.
|
857
|
-
field: The field to validate against.
|
858
|
-
key: The name of the column to validate. Only used for logging.
|
859
|
-
values_setter: A callable that sets the values.
|
860
|
-
source: The source to validate against.
|
861
|
-
"""
|
855
|
+
"""Vector with categorical values."""
|
862
856
|
|
863
857
|
def __init__(
|
864
858
|
self,
|
865
|
-
values_getter: Callable
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
859
|
+
values_getter: Callable
|
860
|
+
| Iterable[str], # A callable or iterable that returns the values to validate.
|
861
|
+
field: FieldAttr, # The field to validate against.
|
862
|
+
key: str, # The name of the vector to validate. Only used for logging.
|
863
|
+
values_setter: Callable | None = None, # A callable that sets the values.
|
864
|
+
source: Record | None = None, # The ontology source to validate against.
|
870
865
|
feature: Feature | None = None,
|
871
866
|
cat_manager: DataFrameCatManager | None = None,
|
872
867
|
subtype_str: str = "",
|
873
|
-
maximal_set: bool =
|
868
|
+
maximal_set: bool = True, # whether unvalidated categoricals cause validation failure.
|
874
869
|
) -> None:
|
875
870
|
self._values_getter = values_getter
|
876
871
|
self._values_setter = values_setter
|
@@ -912,18 +907,20 @@ class CatVector:
|
|
912
907
|
@property
|
913
908
|
def is_validated(self) -> bool:
|
914
909
|
"""Whether the vector is validated."""
|
915
|
-
#
|
916
|
-
#
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
910
|
+
# if nothing was validated, something likely is fundamentally wrong
|
911
|
+
# should probably add a setting `at_least_one_validated`
|
912
|
+
result = True
|
913
|
+
if len(self.values) > 0 and len(self.values) == len(self._non_validated):
|
914
|
+
result = False
|
915
|
+
# len(self._non_validated) != 0
|
916
|
+
# if maximal_set is True, return False
|
917
|
+
# if maximal_set is False, return True
|
918
|
+
# len(self._non_validated) == 0
|
919
|
+
# return True
|
920
|
+
if len(self._non_validated) != 0:
|
921
|
+
if self._maximal_set:
|
922
|
+
result = False
|
923
|
+
return result
|
927
924
|
|
928
925
|
def _replace_synonyms(self) -> list[str]:
|
929
926
|
"""Replace synonyms in the vector with standardized values."""
|
@@ -1078,11 +1075,6 @@ class CatVector:
|
|
1078
1075
|
field_name = self._field.field.name
|
1079
1076
|
model_field = f"{registry.__name__}.{field_name}"
|
1080
1077
|
|
1081
|
-
def _log_mapping_info():
|
1082
|
-
logger.indent = ""
|
1083
|
-
logger.info(f'mapping "{self._key}" on {colors.italic(model_field)}')
|
1084
|
-
logger.indent = " "
|
1085
|
-
|
1086
1078
|
kwargs_current = get_current_filter_kwargs(
|
1087
1079
|
registry, {"organism": self._organism, "source": self._source}
|
1088
1080
|
)
|
@@ -1121,7 +1113,6 @@ class CatVector:
|
|
1121
1113
|
non_validated = [i for i in non_validated if i not in values_validated]
|
1122
1114
|
n_non_validated = len(non_validated)
|
1123
1115
|
if n_non_validated == 0:
|
1124
|
-
logger.indent = ""
|
1125
1116
|
logger.success(
|
1126
1117
|
f'"{self._key}" is validated against {colors.italic(model_field)}'
|
1127
1118
|
)
|
@@ -1143,14 +1134,12 @@ class CatVector:
|
|
1143
1134
|
warning_message += f" → fix typos, remove non-existent values, or save terms via: {colors.cyan(non_validated_hint_print)}"
|
1144
1135
|
if self._subtype_query_set is not None:
|
1145
1136
|
warning_message += f"\n → a valid label for subtype '{self._subtype_str}' has to be one of {self._subtype_query_set.list('name')}"
|
1146
|
-
|
1147
|
-
_log_mapping_info()
|
1137
|
+
logger.info(f'mapping "{self._key}" on {colors.italic(model_field)}')
|
1148
1138
|
logger.warning(warning_message)
|
1149
1139
|
if self._cat_manager is not None:
|
1150
1140
|
self._cat_manager._validate_category_error_messages = strip_ansi_codes(
|
1151
1141
|
warning_message
|
1152
1142
|
)
|
1153
|
-
logger.indent = ""
|
1154
1143
|
return non_validated, syn_mapper
|
1155
1144
|
|
1156
1145
|
def validate(self) -> None:
|
@@ -1218,7 +1207,7 @@ class DataFrameCatManager:
|
|
1218
1207
|
sources: dict[str, Record] | None = None,
|
1219
1208
|
index: Feature | None = None,
|
1220
1209
|
slot: str | None = None,
|
1221
|
-
|
1210
|
+
maximal_set: bool = False,
|
1222
1211
|
) -> None:
|
1223
1212
|
self._non_validated = None
|
1224
1213
|
self._index = index
|
@@ -1235,7 +1224,7 @@ class DataFrameCatManager:
|
|
1235
1224
|
self._validate_category_error_messages: str = ""
|
1236
1225
|
self._cat_vectors: dict[str, CatVector] = {}
|
1237
1226
|
self._slot = slot
|
1238
|
-
self._maximal_set =
|
1227
|
+
self._maximal_set = maximal_set
|
1239
1228
|
|
1240
1229
|
if columns_names is None:
|
1241
1230
|
columns_names = []
|
@@ -1280,7 +1269,6 @@ class DataFrameCatManager:
|
|
1280
1269
|
feature=feature,
|
1281
1270
|
cat_manager=self,
|
1282
1271
|
subtype_str=subtype_str,
|
1283
|
-
maximal_set=self._maximal_set,
|
1284
1272
|
)
|
1285
1273
|
if index is not None and index.dtype.startswith("cat"):
|
1286
1274
|
result = parse_dtype(index.dtype)[0]
|
@@ -1292,7 +1280,6 @@ class DataFrameCatManager:
|
|
1292
1280
|
key=key,
|
1293
1281
|
feature=index,
|
1294
1282
|
cat_manager=self,
|
1295
|
-
maximal_set=self._maximal_set,
|
1296
1283
|
)
|
1297
1284
|
|
1298
1285
|
@property
|
@@ -1330,7 +1317,7 @@ class DataFrameCatManager:
|
|
1330
1317
|
|
1331
1318
|
validated = True
|
1332
1319
|
for key, cat_vector in self._cat_vectors.items():
|
1333
|
-
logger.info(f"validating
|
1320
|
+
logger.info(f"validating vector {key}")
|
1334
1321
|
cat_vector.validate()
|
1335
1322
|
validated &= cat_vector.is_validated
|
1336
1323
|
self._is_validated = validated
|
@@ -1493,6 +1480,9 @@ def annotate_artifact(
|
|
1493
1480
|
else "columns"
|
1494
1481
|
)
|
1495
1482
|
features = slot_curator.cat._cat_vectors[name].records
|
1483
|
+
if features is None:
|
1484
|
+
logger.warning(f"no features found for slot {slot}")
|
1485
|
+
continue
|
1496
1486
|
itype = parse_cat_dtype(artifact.schema.slots[slot].itype, is_itype=True)[
|
1497
1487
|
"field"
|
1498
1488
|
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Generated by Django 5.2 on 2025-05-07 12:16
|
2
|
+
|
3
|
+
from django.db import migrations
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("lamindb", "0092_alter_artifactfeaturevalue_artifact_and_more"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.AlterUniqueTogether(
|
13
|
+
name="schemacomponent",
|
14
|
+
unique_together={("composite", "slot"), ("composite", "slot", "component")},
|
15
|
+
),
|
16
|
+
]
|
@@ -49,7 +49,7 @@ from ._label_manager import _get_labels, describe_labels
|
|
49
49
|
from ._relations import (
|
50
50
|
dict_related_model_to_related_name,
|
51
51
|
)
|
52
|
-
from .feature import Feature, FeatureValue
|
52
|
+
from .feature import Feature, FeatureValue, parse_dtype
|
53
53
|
from .record import Record
|
54
54
|
from .run import Param, ParamManager, ParamManagerRun, ParamValue, Run
|
55
55
|
from .ulabel import ULabel
|
@@ -649,13 +649,22 @@ def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
|
|
649
649
|
if cls == FeatureManager:
|
650
650
|
from .artifact import ArtifactFeatureValue
|
651
651
|
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
652
|
+
if value: # True
|
653
|
+
return Artifact.objects.exclude(
|
654
|
+
id__in=Subquery(
|
655
|
+
ArtifactFeatureValue.objects.filter(
|
656
|
+
featurevalue__feature=feature
|
657
|
+
).values("artifact_id")
|
658
|
+
)
|
659
|
+
)
|
660
|
+
else:
|
661
|
+
return Artifact.objects.exclude(
|
662
|
+
id__in=Subquery(
|
663
|
+
ArtifactFeatureValue.objects.filter(
|
664
|
+
featurevalue__feature=feature
|
665
|
+
).values("artifact_id")
|
666
|
+
)
|
657
667
|
)
|
658
|
-
)
|
659
668
|
if comparator in {"__startswith", "__contains"}:
|
660
669
|
logger.important(
|
661
670
|
f"currently not supporting `{comparator}`, using `__icontains` instead"
|
@@ -667,7 +676,14 @@ def filter_base(cls, _skip_validation: bool = True, **expression) -> QuerySet:
|
|
667
676
|
elif isinstance(value, (str, Record, bool)):
|
668
677
|
if comparator == "__isnull":
|
669
678
|
if cls == FeatureManager:
|
670
|
-
|
679
|
+
result = parse_dtype(feature.dtype)[0]
|
680
|
+
kwargs = {
|
681
|
+
f"links_{result['registry'].__name__.lower()}__feature": feature
|
682
|
+
}
|
683
|
+
if value: # True
|
684
|
+
return Artifact.objects.exclude(**kwargs)
|
685
|
+
else:
|
686
|
+
return Artifact.objects.filter(**kwargs)
|
671
687
|
else:
|
672
688
|
# because SQL is sensitive to whether querying with __in or not
|
673
689
|
# and might return multiple equivalent records for the latter
|
lamindb/models/artifact.py
CHANGED
@@ -17,7 +17,6 @@ from django.db.models import CASCADE, PROTECT, Q
|
|
17
17
|
from lamin_utils import colors, logger
|
18
18
|
from lamindb_setup import settings as setup_settings
|
19
19
|
from lamindb_setup._init_instance import register_storage_in_instance
|
20
|
-
from lamindb_setup.core import doc_args
|
21
20
|
from lamindb_setup.core._settings_storage import init_storage
|
22
21
|
from lamindb_setup.core.hashing import HASH_LENGTH, hash_dir, hash_file
|
23
22
|
from lamindb_setup.core.types import UPathStr
|
@@ -99,8 +98,6 @@ WARNING_RUN_TRANSFORM = "no run & transform got linked, call `ln.track()` & re-r
|
|
99
98
|
|
100
99
|
WARNING_NO_INPUT = "run input wasn't tracked, call `ln.track()` and re-run"
|
101
100
|
|
102
|
-
DEBUG_KWARGS_DOC = "**kwargs: Internal arguments for debugging."
|
103
|
-
|
104
101
|
try:
|
105
102
|
from ..core.storage._zarr import identify_zarr_type
|
106
103
|
except ImportError:
|
@@ -914,7 +911,7 @@ def add_labels(
|
|
914
911
|
for registry_name, records in records_by_registry.items():
|
915
912
|
if not from_curator and feature.name in internal_features:
|
916
913
|
raise ValidationError(
|
917
|
-
"Cannot manually annotate
|
914
|
+
"Cannot manually annotate a feature measured *within* the dataset. Please use a Curator."
|
918
915
|
)
|
919
916
|
if registry_name not in feature.dtype:
|
920
917
|
if not feature.dtype.startswith("cat"):
|
@@ -1236,7 +1233,7 @@ class Artifact(Record, IsVersioned, TracksRun, TracksUpdates):
|
|
1236
1233
|
default=None,
|
1237
1234
|
related_name="validated_artifacts",
|
1238
1235
|
)
|
1239
|
-
"""The schema that validated this artifact in a :class:`~lamindb.curators.Curator`."""
|
1236
|
+
"""The schema that validated this artifact in a :class:`~lamindb.curators.core.Curator`."""
|
1240
1237
|
feature_sets: Schema = models.ManyToManyField(
|
1241
1238
|
Schema, related_name="artifacts", through="ArtifactSchema"
|
1242
1239
|
)
|
@@ -2363,6 +2360,11 @@ class Artifact(Record, IsVersioned, TracksRun, TracksUpdates):
|
|
2363
2360
|
|
2364
2361
|
if hasattr(self, "_memory_rep") and self._memory_rep is not None:
|
2365
2362
|
access_memory = self._memory_rep
|
2363
|
+
# SpatialData objects zarr stores are moved when saved
|
2364
|
+
# SpatialData's __repr__ method attempts to access information from the old path
|
2365
|
+
# Therefore, we need to update the in-memory path to the now moved Artifact storage path
|
2366
|
+
if access_memory.__class__.__name__ == "SpatialData":
|
2367
|
+
access_memory.path = self._cache_path
|
2366
2368
|
else:
|
2367
2369
|
filepath, cache_key = filepath_cache_key_from_artifact(
|
2368
2370
|
self, using_key=settings._using_key
|
@@ -2395,9 +2397,9 @@ class Artifact(Record, IsVersioned, TracksRun, TracksUpdates):
|
|
2395
2397
|
access_memory = load_to_memory(cache_path, **kwargs)
|
2396
2398
|
# only call if load is successfull
|
2397
2399
|
_track_run_input(self, is_run_input)
|
2400
|
+
|
2398
2401
|
return access_memory
|
2399
2402
|
|
2400
|
-
@doc_args(DEBUG_KWARGS_DOC)
|
2401
2403
|
def cache(
|
2402
2404
|
self, *, is_run_input: bool | None = None, mute: bool = False, **kwargs
|
2403
2405
|
) -> Path:
|
@@ -2410,7 +2412,6 @@ class Artifact(Record, IsVersioned, TracksRun, TracksUpdates):
|
|
2410
2412
|
Args:
|
2411
2413
|
mute: Silence logging of caching progress.
|
2412
2414
|
is_run_input: Whether to track this artifact as run input.
|
2413
|
-
{}
|
2414
2415
|
|
2415
2416
|
Example::
|
2416
2417
|
|
@@ -2560,13 +2561,11 @@ class Artifact(Record, IsVersioned, TracksRun, TracksUpdates):
|
|
2560
2561
|
if delete_msg != "did-not-delete":
|
2561
2562
|
logger.success(f"deleted {colors.yellow(f'{path}')}")
|
2562
2563
|
|
2563
|
-
@doc_args(DEBUG_KWARGS_DOC)
|
2564
2564
|
def save(self, upload: bool | None = None, **kwargs) -> Artifact:
|
2565
2565
|
"""Save to database & storage.
|
2566
2566
|
|
2567
2567
|
Args:
|
2568
2568
|
upload: Trigger upload to cloud storage in instances with hybrid storage mode.
|
2569
|
-
{}
|
2570
2569
|
|
2571
2570
|
Example::
|
2572
2571
|
|
@@ -2763,8 +2762,8 @@ def _track_run_input(
|
|
2763
2762
|
# record is on another db
|
2764
2763
|
# we have to save the record into the current db with
|
2765
2764
|
# the run being attached to a transfer transform
|
2766
|
-
logger.
|
2767
|
-
f"completing transfer to track {data.__class__.__name__}('{data.uid[:8]}') as input"
|
2765
|
+
logger.info(
|
2766
|
+
f"completing transfer to track {data.__class__.__name__}('{data.uid[:8]}...') as input"
|
2768
2767
|
)
|
2769
2768
|
data.save()
|
2770
2769
|
is_valid = True
|
lamindb/models/has_parents.py
CHANGED
@@ -84,10 +84,44 @@ class HasParents:
|
|
84
84
|
return view_parents(
|
85
85
|
record=self, # type: ignore
|
86
86
|
field=field,
|
87
|
+
with_parents=True,
|
87
88
|
with_children=with_children,
|
88
89
|
distance=distance,
|
89
90
|
)
|
90
91
|
|
92
|
+
def view_children(
|
93
|
+
self,
|
94
|
+
field: StrField | None = None,
|
95
|
+
distance: int = 5,
|
96
|
+
):
|
97
|
+
"""View children in an ontology.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
field: Field to display on graph
|
101
|
+
distance: Maximum distance still shown.
|
102
|
+
|
103
|
+
Ontological hierarchies: :class:`~lamindb.ULabel` (project & sub-project), :class:`~bionty.CellType` (cell type & subtype).
|
104
|
+
|
105
|
+
Examples:
|
106
|
+
>>> import bionty as bt
|
107
|
+
>>> bt.Tissue.from_source(name="subsegmental bronchus").save()
|
108
|
+
>>> record = bt.Tissue.get(name="respiratory tube")
|
109
|
+
>>> record.view_parents()
|
110
|
+
>>> tissue.view_parents(with_children=True)
|
111
|
+
"""
|
112
|
+
if field is None:
|
113
|
+
field = get_name_field(self)
|
114
|
+
if not isinstance(field, str):
|
115
|
+
field = field.field.name
|
116
|
+
|
117
|
+
return view_parents(
|
118
|
+
record=self, # type: ignore
|
119
|
+
field=field,
|
120
|
+
with_parents=False,
|
121
|
+
with_children=True,
|
122
|
+
distance=distance,
|
123
|
+
)
|
124
|
+
|
91
125
|
def query_parents(self) -> QuerySet:
|
92
126
|
"""Query parents in an ontology."""
|
93
127
|
return _query_relatives([self], "parents", self.__class__) # type: ignore
|
@@ -210,6 +244,7 @@ def view_lineage(
|
|
210
244
|
def view_parents(
|
211
245
|
record: Record,
|
212
246
|
field: str,
|
247
|
+
with_parents: bool = True,
|
213
248
|
with_children: bool = False,
|
214
249
|
distance: int = 100,
|
215
250
|
attr_name: Literal["parents", "predecessors"] = "parents",
|
@@ -223,11 +258,12 @@ def view_parents(
|
|
223
258
|
import pandas as pd
|
224
259
|
|
225
260
|
df_edges = None
|
226
|
-
df_edges_parents =
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
261
|
+
df_edges_parents = None
|
262
|
+
df_edges_children = None
|
263
|
+
if with_parents:
|
264
|
+
df_edges_parents = _df_edges_from_parents(
|
265
|
+
record=record, field=field, distance=distance, attr_name=attr_name
|
266
|
+
)
|
231
267
|
if with_children:
|
232
268
|
df_edges_children = _df_edges_from_parents(
|
233
269
|
record=record,
|
@@ -236,13 +272,32 @@ def view_parents(
|
|
236
272
|
children=True,
|
237
273
|
attr_name=attr_name,
|
238
274
|
)
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
275
|
+
# Rename the columns to swap source and target
|
276
|
+
df_edges_children = df_edges_children.rename(
|
277
|
+
columns={
|
278
|
+
"source": "temp_target",
|
279
|
+
"source_label": "temp_target_label",
|
280
|
+
"source_record": "temp_target_record",
|
281
|
+
"target": "source",
|
282
|
+
"target_label": "source_label",
|
283
|
+
"target_record": "source_record",
|
284
|
+
}
|
285
|
+
)
|
286
|
+
df_edges_children = df_edges_children.rename(
|
287
|
+
columns={
|
288
|
+
"temp_target": "target",
|
289
|
+
"temp_target_label": "target_label",
|
290
|
+
"temp_target_record": "target_record",
|
291
|
+
}
|
292
|
+
)
|
293
|
+
if df_edges_parents is not None and df_edges_children is not None:
|
294
|
+
df_edges = pd.concat([df_edges_parents, df_edges_children]).drop_duplicates()
|
295
|
+
elif df_edges_parents is not None:
|
296
|
+
df_edges = df_edges_parents
|
297
|
+
elif df_edges_children is not None:
|
298
|
+
df_edges = df_edges_children
|
299
|
+
else:
|
300
|
+
return None
|
246
301
|
|
247
302
|
record_label = _record_label(record, field)
|
248
303
|
|
lamindb/models/query_set.py
CHANGED
@@ -430,8 +430,9 @@ def reshape_annotate_result(
|
|
430
430
|
"""
|
431
431
|
cols_from_include = cols_from_include or {}
|
432
432
|
|
433
|
-
# initialize result with basic fields
|
434
|
-
|
433
|
+
# initialize result with basic fields, need a copy as we're modifying it
|
434
|
+
# will give us warnings otherwise
|
435
|
+
result = df[field_names].copy()
|
435
436
|
# process features if requested
|
436
437
|
if feature_names:
|
437
438
|
# handle feature_values
|
lamindb/models/record.py
CHANGED
@@ -596,9 +596,8 @@ class Registry(ModelBase):
|
|
596
596
|
|
597
597
|
target_modules = setup_settings.instance.modules
|
598
598
|
if missing_members := source_modules - target_modules:
|
599
|
-
logger.
|
600
|
-
f"source
|
601
|
-
"consider mounting these registry modules to transfer all metadata"
|
599
|
+
logger.info(
|
600
|
+
f"in transfer, source lamindb instance has additional modules: {', '.join(missing_members)}"
|
602
601
|
)
|
603
602
|
|
604
603
|
add_db_connection(db, instance)
|
@@ -839,7 +838,7 @@ class BasicRecord(models.Model, metaclass=Registry):
|
|
839
838
|
self.features._add_from(self_on_db, transfer_logs=transfer_logs)
|
840
839
|
self.labels.add_from(self_on_db, transfer_logs=transfer_logs)
|
841
840
|
for k, v in transfer_logs.items():
|
842
|
-
if k != "run":
|
841
|
+
if k != "run" and len(v) > 0:
|
843
842
|
logger.important(f"{k} records: {', '.join(v)}")
|
844
843
|
|
845
844
|
if (
|
lamindb/models/schema.py
CHANGED
@@ -439,7 +439,7 @@ class Schema(Record, CanCurate, TracksRun):
|
|
439
439
|
artifacts: Artifact
|
440
440
|
"""The artifacts that measure a feature set that matches this schema."""
|
441
441
|
validated_artifacts: Artifact
|
442
|
-
"""The artifacts that were validated against this schema with a :class:`~lamindb.curators.Curator`."""
|
442
|
+
"""The artifacts that were validated against this schema with a :class:`~lamindb.curators.core.Curator`."""
|
443
443
|
projects: Project
|
444
444
|
"""Linked projects."""
|
445
445
|
_curation: dict[str, Any] = JSONField(default=None, db_default=None, null=True)
|
@@ -457,7 +457,7 @@ class Schema(Record, CanCurate, TracksRun):
|
|
457
457
|
# For instance, the set of measured features might be a superset of the minimally required set of features.
|
458
458
|
# """
|
459
459
|
# validated_schemas: Schema
|
460
|
-
# """The schemas that were validated against this schema with a :class:`~lamindb.curators.Curator`."""
|
460
|
+
# """The schemas that were validated against this schema with a :class:`~lamindb.curators.core.Curator`."""
|
461
461
|
composite: Schema | None = ForeignKey(
|
462
462
|
"self", PROTECT, related_name="+", default=None, null=True
|
463
463
|
)
|
@@ -538,7 +538,6 @@ class Schema(Record, CanCurate, TracksRun):
|
|
538
538
|
optional_features,
|
539
539
|
features_registry,
|
540
540
|
flexible,
|
541
|
-
list_for_hashing,
|
542
541
|
) = self._validate_kwargs_calculate_hash(
|
543
542
|
features=features,
|
544
543
|
index=index,
|
@@ -562,7 +561,6 @@ class Schema(Record, CanCurate, TracksRun):
|
|
562
561
|
.filter(hash=validated_kwargs["hash"])
|
563
562
|
.one_or_none()
|
564
563
|
)
|
565
|
-
self._list_for_hashing = list_for_hashing
|
566
564
|
if schema is not None:
|
567
565
|
logger.important(f"returning existing schema with same hash: {schema}")
|
568
566
|
init_self_from_db(self, schema)
|
@@ -609,7 +607,7 @@ class Schema(Record, CanCurate, TracksRun):
|
|
609
607
|
coerce_dtype: bool,
|
610
608
|
n_features: int | None,
|
611
609
|
optional_features_manual: list[Feature] | None = None,
|
612
|
-
) -> tuple[list[Feature], dict[str, Any], list[Feature], Registry, bool
|
610
|
+
) -> tuple[list[Feature], dict[str, Any], list[Feature], Registry, bool]:
|
613
611
|
optional_features = []
|
614
612
|
features_registry: Registry = None
|
615
613
|
if itype is not None:
|
@@ -729,7 +727,6 @@ class Schema(Record, CanCurate, TracksRun):
|
|
729
727
|
optional_features,
|
730
728
|
features_registry,
|
731
729
|
flexible,
|
732
|
-
list_for_hashing,
|
733
730
|
)
|
734
731
|
|
735
732
|
@classmethod
|
@@ -865,26 +862,24 @@ class Schema(Record, CanCurate, TracksRun):
|
|
865
862
|
if hasattr(self, "_features")
|
866
863
|
else (self.members.list() if self.members.exists() else [])
|
867
864
|
)
|
868
|
-
_, validated_kwargs, _, _, _
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
optional_features_manual=self.optionals.get(),
|
887
|
-
)
|
865
|
+
_, validated_kwargs, _, _, _ = self._validate_kwargs_calculate_hash(
|
866
|
+
features=features, # type: ignore
|
867
|
+
index=None, # need to pass None here as otherwise counting double
|
868
|
+
slots=self.slots,
|
869
|
+
name=self.name,
|
870
|
+
description=self.description,
|
871
|
+
itype=self.itype,
|
872
|
+
flexible=self.flexible,
|
873
|
+
type=self.type,
|
874
|
+
is_type=self.is_type,
|
875
|
+
otype=self.otype,
|
876
|
+
dtype=self.dtype,
|
877
|
+
minimal_set=self.minimal_set,
|
878
|
+
ordered_set=self.ordered_set,
|
879
|
+
maximal_set=self.maximal_set,
|
880
|
+
coerce_dtype=self.coerce_dtype,
|
881
|
+
n_features=self.n,
|
882
|
+
optional_features_manual=self.optionals.get(),
|
888
883
|
)
|
889
884
|
if validated_kwargs["hash"] != self.hash:
|
890
885
|
from .artifact import Artifact
|
@@ -896,7 +891,6 @@ class Schema(Record, CanCurate, TracksRun):
|
|
896
891
|
)
|
897
892
|
self.hash = validated_kwargs["hash"]
|
898
893
|
self.n = validated_kwargs["n"]
|
899
|
-
self._list_for_hashing = list_for_hashing
|
900
894
|
super().save(*args, **kwargs)
|
901
895
|
if hasattr(self, "_slots"):
|
902
896
|
# analogous to save_schema_links in core._data.py
|
@@ -910,6 +904,7 @@ class Schema(Record, CanCurate, TracksRun):
|
|
910
904
|
}
|
911
905
|
links.append(Schema.components.through(**kwargs))
|
912
906
|
bulk_create(links, ignore_conflicts=True)
|
907
|
+
delattr(self, "_slots")
|
913
908
|
if hasattr(self, "_features"):
|
914
909
|
assert self.n > 0 # noqa: S101
|
915
910
|
using: bool | None = kwargs.pop("using", None)
|
@@ -1188,7 +1183,7 @@ class SchemaComponent(BasicRecord, LinkORM, TracksRun):
|
|
1188
1183
|
slot: str | None = CharField(null=True)
|
1189
1184
|
|
1190
1185
|
class Meta:
|
1191
|
-
unique_together = (("composite", "component"), ("composite", "slot"))
|
1186
|
+
unique_together = (("composite", "slot", "component"), ("composite", "slot"))
|
1192
1187
|
|
1193
1188
|
|
1194
1189
|
Schema._get_related_name = _get_related_name
|
@@ -1,4 +1,4 @@
|
|
1
|
-
lamindb/__init__.py,sha256=
|
1
|
+
lamindb/__init__.py,sha256=yrNn0pSKCbdmvx_KKQ98PZraCdjzqMPwcwlHR3IoDvg,2676
|
2
2
|
lamindb/_finish.py,sha256=Wqb846pCErsx5ZPulAfdF5PJbWzgAdfbuYuf4FndfhY,20124
|
3
3
|
lamindb/_tracked.py,sha256=fse_H0ehc9WvU_l1572g7qya0sRdWCh22LZkq0XU4ic,4445
|
4
4
|
lamindb/_view.py,sha256=kSmG8X4ULQZEKxY7ESnthQqsUf1DEzoYGeTLYRU1I7s,4938
|
@@ -11,7 +11,7 @@ lamindb/base/uids.py,sha256=cLBi5mIlsf1ltkTb17r1FLzlOjlGmjvsCygoVJHQ-A8,2116
|
|
11
11
|
lamindb/base/users.py,sha256=8MSmAvCKoUF15YsDE6BGLBXsFWpfoEEg8iDTKZ7kD48,848
|
12
12
|
lamindb/core/__init__.py,sha256=aaBq0UVjNolMynbT1V5hB6UrJm1tK0M6WHu_r6em9_4,604
|
13
13
|
lamindb/core/_compat.py,sha256=NLnKk1qk4xdgMV-QwFDnBnbio02ujjlF86icvhpdv4c,2029
|
14
|
-
lamindb/core/_context.py,sha256=
|
14
|
+
lamindb/core/_context.py,sha256=xKj4YGpgM3Dx8H7_rNf6EI3sC5JHScSYVgHw-QYbMp4,34679
|
15
15
|
lamindb/core/_mapped_collection.py,sha256=dxyZ1ZHFn5SBl1xILqN9N6TTUJP0PptVBV-2O0EdZww,25751
|
16
16
|
lamindb/core/_settings.py,sha256=DAeEN2Qswj6VDlM7OE5YtoteMfFZ61CmMwcS056_scE,6211
|
17
17
|
lamindb/core/_sync_git.py,sha256=Z7keuyS5X7CAj285sEbZIFExZF9mtjGH8DzKwz3xhHw,5881
|
@@ -30,7 +30,7 @@ lamindb/core/storage/_anndata_sizes.py,sha256=aXO3OB--tF5MChenSsigW6Q-RuE8YJJOUT
|
|
30
30
|
lamindb/core/storage/_backed_access.py,sha256=LlpRDZ0skseZA5tBFu3-cH1wJwuXm7-NS2RgnTK7wgc,7382
|
31
31
|
lamindb/core/storage/_polars_lazy_df.py,sha256=Z0KMp0OU5S36L5g8EuJk7V_nn-spgG1lFeEFnkTOLcw,1350
|
32
32
|
lamindb/core/storage/_pyarrow_dataset.py,sha256=lRYYt7edUtwauhxd7RwFud6YPDbz2PFvYYgqLhfapfk,1398
|
33
|
-
lamindb/core/storage/_tiledbsoma.py,sha256=
|
33
|
+
lamindb/core/storage/_tiledbsoma.py,sha256=QLMOPjdxv9JFs9JR0Kqg1UTkJKNgwIDMeHAewB0-Lqg,11124
|
34
34
|
lamindb/core/storage/_valid_suffixes.py,sha256=vUSeQ4s01rdhD_vSd6wKmFBsgMJAKkBMnL_T9Y1znMg,501
|
35
35
|
lamindb/core/storage/_zarr.py,sha256=cisYXU4_QXMF_ZY2pV52Incus6365mMxRphLaHO76W0,6801
|
36
36
|
lamindb/core/storage/objects.py,sha256=n1Kj1soxF-_iLFyNnHriVFcngw6nqEAd7aVm0Hm8Tcw,3017
|
@@ -40,7 +40,7 @@ lamindb/core/subsettings/_annotation_settings.py,sha256=o-yTYw-NmjFmtehbKU8qnf7t
|
|
40
40
|
lamindb/core/subsettings/_creation_settings.py,sha256=NGHWKqCFSzVNBxAr2VnmdYguiFdW29XUK7T9wRsVshg,906
|
41
41
|
lamindb/curators/__init__.py,sha256=ZexikeaVunT24TqsR1NsSOCSBXDBigfGtFT55tBwqS8,371
|
42
42
|
lamindb/curators/_legacy.py,sha256=dTim3YFvdYyMsn6y8qSYkbCnnEI4tlaevN2-OO_qEx8,76174
|
43
|
-
lamindb/curators/core.py,sha256=
|
43
|
+
lamindb/curators/core.py,sha256=YwMcKV2rAEhTav_fBixMM_sON2iUeu8JHGgxgcTjBn4,59915
|
44
44
|
lamindb/curators/_cellxgene_schemas/__init__.py,sha256=zqlFzMNMDGEBe6DV0gBsBMpfc9UHvNv1EpBsz_ktMoA,7502
|
45
45
|
lamindb/curators/_cellxgene_schemas/schema_versions.csv,sha256=X9rmO88TW1Fht1f5mJs0JdW-VPvyKSajpf8lHNeECj4,1680
|
46
46
|
lamindb/examples/__init__.py,sha256=DGImiuWYDvwxh78p5FCwQWClEwsE3ODLU49i_NqbW0c,533
|
@@ -74,35 +74,36 @@ lamindb/migrations/0090_runproject_project_runs.py,sha256=Ab9wyGxc6xjBfj-36cqdTl
|
|
74
74
|
lamindb/migrations/0090_squashed.py,sha256=kx_A_25BYantikxCbGhJughFpv_lqyHH86pMh5YevEE,160823
|
75
75
|
lamindb/migrations/0091_alter_featurevalue_options_alter_space_options_and_more.py,sha256=Df4EYAQlLKZ4BpFcsRRF52pGN3hDSo94laiO-V90Kn4,607
|
76
76
|
lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py,sha256=x-2Pvi0GJugkLrR--Fw9PBzV-HxqXjl0NktxRtRFJno,2459
|
77
|
+
lamindb/migrations/0093_alter_schemacomponent_unique_together.py,sha256=p6pCGU3xzOo5FuHE_COxVn6qLgRUAdfWXJjl4_euEKU,424
|
77
78
|
lamindb/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
78
79
|
lamindb/models/__init__.py,sha256=IFYoZfly3m0Me5Fr8sk6-KdYpVzkuug0lo8jvci00Kg,2080
|
79
80
|
lamindb/models/_describe.py,sha256=4PxaavWidEL8cyV2idbpC_7Zo0Jmjam3X1Bwe71IMaY,5489
|
80
81
|
lamindb/models/_django.py,sha256=2LFaTvIPtxIV8_T6Kx0cvquTetj7C3OcnKukUyC9msY,7705
|
81
|
-
lamindb/models/_feature_manager.py,sha256=
|
82
|
+
lamindb/models/_feature_manager.py,sha256=uMIcQMYrH1bHCqzovDbkDUOsBre_-mrg_7OS4RdoR8c,54666
|
82
83
|
lamindb/models/_from_values.py,sha256=-8l3_d2Nm14kzi1FjEYvBwyuucL-ZcDSjlMufIb4XoQ,13324
|
83
84
|
lamindb/models/_is_versioned.py,sha256=Th2_cBf9UWh27E6ANxg6LGmjBOumXFy7AjH0GG4FoXA,7601
|
84
85
|
lamindb/models/_label_manager.py,sha256=QOT6mz_rzPJ5p7hM1l-XzDWzyWUERpmAan2n_ma5wpI,12112
|
85
86
|
lamindb/models/_relations.py,sha256=ONjHPiWIa_Ur7zMNTa_9Uw7K-366GORyPvGoVjf4EQs,3681
|
86
|
-
lamindb/models/artifact.py,sha256=
|
87
|
+
lamindb/models/artifact.py,sha256=6F_jcZiG1LeLT5HKSPCBiKUU-ItFM24aHyqWrwl1egc,110565
|
87
88
|
lamindb/models/artifact_set.py,sha256=VOZEGDo3m_9Yg_ftx3I2fwdydjHN61X_qV18N6xG4kM,4117
|
88
89
|
lamindb/models/can_curate.py,sha256=5dXHCRoJzLg2y9YDhpH7CyWexxliFHilwJ_UPjjZwRI,29188
|
89
90
|
lamindb/models/collection.py,sha256=TNXnrR86ZgsSfEvaOuAEItgZ947klTXXZspa7hpyVmw,27288
|
90
91
|
lamindb/models/core.py,sha256=A-W_Hdg4AmbBFBU38SEEVhOwSIzww5oNgYAQFnwOO7A,4018
|
91
92
|
lamindb/models/feature.py,sha256=WoT29eZ8DR6MTZgnztbRye3-zX4BRYfJ8HlhdenX2qA,28186
|
92
93
|
lamindb/models/flextable.py,sha256=ET9j0fTFYQIdXOZfwCnosXOag7nYD1DUV6_wZNqhvOs,5400
|
93
|
-
lamindb/models/has_parents.py,sha256=
|
94
|
+
lamindb/models/has_parents.py,sha256=A8OWsNotWlFrZB2pURRxp8EcHJ1kIlyV5eMnajGgkh4,20328
|
94
95
|
lamindb/models/project.py,sha256=Hm-5hLn-FffFK3J_68gt-AxVc6bo26fegwGFRw0Gp50,15225
|
95
96
|
lamindb/models/query_manager.py,sha256=mqsULCmUQf5ibpSXazca9ZYxyZwiDLuzSm8s6dPrl_M,10712
|
96
|
-
lamindb/models/query_set.py,sha256=
|
97
|
-
lamindb/models/record.py,sha256=
|
97
|
+
lamindb/models/query_set.py,sha256=xKh5QjAlHunktB1S4x9f42Fg0SP_-sK7XlyxStIRDSo,30385
|
98
|
+
lamindb/models/record.py,sha256=fomXuOcqkfiYF3zEdiUkYw9x00qP5flM7oseUUomhIo,61354
|
98
99
|
lamindb/models/run.py,sha256=FzqVQhYj4DXqlnmHvNIziOCAlx9K0wISXBLpom1Yb74,20688
|
99
100
|
lamindb/models/save.py,sha256=JTAaorKECx0ZeHaX0H9Yt4MDwOsT9F813WbSJkBIPaU,13339
|
100
|
-
lamindb/models/schema.py,sha256=
|
101
|
+
lamindb/models/schema.py,sha256=5_31iIPh19eJn0rm1OTeFk0gtD0YUPrTbiPsglKWOeo,47753
|
101
102
|
lamindb/models/transform.py,sha256=LGnTR7g_rAx3YFAFv4l4_UzabruKQlnui1Y3tlWHwXk,12731
|
102
103
|
lamindb/models/ulabel.py,sha256=yn9ttz28MqDBh6ZgwH7cty6GHCJOzLJn2IEpspYosDo,8793
|
103
104
|
lamindb/setup/__init__.py,sha256=OwZpZzPDv5lPPGXZP7-zK6UdO4FHvvuBh439yZvIp3A,410
|
104
105
|
lamindb/setup/core/__init__.py,sha256=SevlVrc2AZWL3uALbE5sopxBnIZPWZ1IB0NBDudiAL8,167
|
105
|
-
lamindb-1.5.
|
106
|
-
lamindb-1.5.
|
107
|
-
lamindb-1.5.
|
108
|
-
lamindb-1.5.
|
106
|
+
lamindb-1.5.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
107
|
+
lamindb-1.5.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
108
|
+
lamindb-1.5.2.dist-info/METADATA,sha256=d13GwaEiF6_3iCOJIBVB3XVQJTt5wQhptuk77Te4JZM,2782
|
109
|
+
lamindb-1.5.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|