Transfer data
¶
This guide shows how to transfer data from a source database to your default database.
# pip install lamindb
!lamin init --storage ./test-transfer --modules bionty
Show code cell output
! using anonymous user (to identify, call: lamin login)
→ initialized lamindb: anonymous/test-transfer
import lamindb as ln
ln.track()
Show code cell output
→ connected lamindb: anonymous/test-transfer
→ created Transform('qGqTBOkr0kO30000', key='transfer.ipynb'), started new Run('1fno97DClZA8Hf79') at 2026-03-06 16:22:45 UTC
→ notebook imports: lamindb==2.3a2
• recommendation: to identify the notebook across renames, pass the uid: ln.track("qGqTBOkr0kO3")
Query artifacts in the laminlabs/lamindata instance:
db = ln.DB("laminlabs/lamindata")
artifacts = db.Artifact.filter(is_latest=True) # query latest versions of artifacts
artifacts.to_dataframe()
Show code cell output
! connecting in read-only mode, please use ln.DB("laminlabs/lamindata") instead
| uid | key | description | suffix | kind | otype | size | hash | n_files | n_observations | ... | is_latest | is_locked | created_at | branch_id | created_on_id | space_id | storage_id | run_id | schema_id | created_by_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||||||||||
| 14816 | 27MZjrMym0DTtCBd0000 | None | Output artifact for run 3607 | .json | None | None | 136.0 | BsTcLuhe0w7O5IYkA2ojfA | None | None | ... | True | False | 2026-02-17 16:23:36.288733+00:00 | 1 | 1 | 1 | 2 | 3607 | None | 18 |
| 14815 | TXlXZi1nKwi3Ll8v0000 | None | Output artifact for run 3607 | .json | None | None | 136.0 | mDuJ3wVCDL7bTXxqeBwAIA | None | None | ... | True | False | 2026-02-17 16:23:25.600803+00:00 | 1 | 1 | 1 | 2 | 3607 | None | 18 |
| 14814 | 5yytZmIQcn1v5GVT0000 | None | CSV upload test 6abca3f4 | .csv | None | DataFrame | 40.0 | 66L0Oyy-cZzfG-oXXEDa9Q | None | None | ... | True | False | 2026-02-17 16:22:46.907699+00:00 | 1 | 1 | 1 | 2 | 3605 | None | 18 |
| 14813 | CI37woHghFAZkFTn0000 | None | Output artifact for run 3606 | .json | None | None | 136.0 | AVzWzmM9nYiD99Z5o_im9w | None | None | ... | True | False | 2026-02-17 16:22:44.364521+00:00 | 1 | 1 | 1 | 2 | 3606 | None | 18 |
| 14812 | 1K7glfLch7FzXCqU0000 | None | Output artifact for run 3606 | .json | None | None | 136.0 | DNB9u8yhYa0UHg-WX-jKow | None | None | ... | True | False | 2026-02-17 16:22:41.282760+00:00 | 1 | 1 | 1 | 2 | 3606 | None | 18 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 14353 | dxoQZ5pXVJyHwUG00000 | None | Output artifact for run 3296 | .json | None | None | 136.0 | aBkW09TY3jkVLY6y_-1nPA | None | None | ... | True | False | 2026-02-12 05:38:30.876474+00:00 | 1 | 1 | 1 | 2 | 3296 | None | 18 |
| 14352 | ien2afXgPzp8ygLb0000 | None | Output artifact for run 3295 | .json | None | None | 136.0 | plYUpERdc8OB0YRcZLjY0A | None | None | ... | True | False | 2026-02-12 05:38:20.616474+00:00 | 1 | 1 | 1 | 2 | 3295 | None | 18 |
| 14351 | uYZZlaed7PeBDeuy0000 | None | Output artifact for run 3295 | .json | None | None | 136.0 | _5jlNz2oD4SYXAP7y0o-QA | None | None | ... | True | False | 2026-02-12 05:38:17.668522+00:00 | 1 | 1 | 1 | 2 | 3295 | None | 18 |
| 14340 | srk2kRVB08mNJbAN0000 | None | Output artifact for run 3282 | .json | None | None | 136.0 | I-fgscFE8n9ucJu-SHnSdg | None | None | ... | True | False | 2026-02-11 19:57:05.529994+00:00 | 1 | 1 | 1 | 2 | 3282 | None | 18 |
| 14339 | k4DTOtEwfB5cBfot0000 | None | Output artifact for run 3281 | .json | None | None | 136.0 | c9sXz6BNjI7STfKx9E1MyA | None | None | ... | True | False | 2026-02-11 19:56:59.914324+00:00 | 1 | 1 | 1 | 2 | 3281 | None | 18 |
100 rows × 21 columns
You can now further subset or search the QuerySet. Here we already know what we’re looking for:
artifact = artifacts.get(key="example_datasets/mini_immuno/dataset1.h5ad")
artifact.describe()
Show code cell output
Artifact: example_datasets/mini_immuno/dataset1.h5ad (0000) | description: Flow cytometry readouts on invitro cell culture ├── uid: 9K1dteZ6Qx0EXK8g0000 run: VioVE27 (curate-anndata-mini-immuno.ipynb) │ kind: dataset otype: AnnData │ hash: FB3CeMjmg1ivN6HDy6wsSg size: 30.9 KB │ branch: main space: all │ created_at: 2025-07-29 12:27:25 UTC created_by: falexwolf │ n_observations: 3.0 ├── storage/path: s3://lamindata/.lamindb/9K1dteZ6Qx0EXK8g0000.h5ad ├── Dataset features │ ├── obs (8.0) │ │ assay_oid bionty.ExperimentalFactor.ontology… EFO:0008913 │ │ cell_type_by_expert bionty.CellType B cell, CD8-positive, alpha-beta T cell │ │ cell_type_by_model bionty.CellType B cell, T cell │ │ concentration str │ │ donor str │ │ perturbation ULabel DMSO, IFNG │ │ sample_note str │ │ treatment_time_h num │ └── var.T (3.0 bionty.Gene.ensem… │ CD14 num │ CD4 num │ CD8A num ├── External features │ └── experiment Record[6pjoBrrz4f1EzQMO] EXP-scRNA-002 │ experiment ULabel Experiment 1 │ date_of_study date 2024-12-01 │ study_metadata dict {'detail1': '123', 'detail2': 1} │ study_note str We had a great time performing this st… │ temperature float 21.6 └── Labels └── .ulabels ULabel DMSO, IFNG, Experiment 1 .records Record EXP-scRNA-002 .projects Project Tutorials .cell_types bionty.CellType B cell, T cell, CD8-positive, alpha-be… .experimental_factors bionty.ExperimentalFactor single-cell RNA sequencing
By saving the artifact that’s currently attached to the source database, you transfer it to your default database.
artifact.save()
Show code cell output
→ transferred: Artifact(uid='9K1dteZ6Qx0EXK8g0000'), Storage(uid='D9BilDV2'), Schema(uid='0000000000000002')
Artifact(uid='9K1dteZ6Qx0EXK8g0000', version_tag=None, is_latest=True, key='example_datasets/mini_immuno/dataset1.h5ad', description='Flow cytometry readouts on invitro cell culture', suffix='.h5ad', kind='dataset', otype='AnnData', size=31672.0, hash='FB3CeMjmg1ivN6HDy6wsSg', n_files=None, n_observations=3.0, branch_id=1, created_on_id=1, space_id=1, storage_id=2, run_id=2, schema_id=1, created_by_id=1, created_at=2025-07-29 12:27:25 UTC, is_locked=False)
How do I know if an object is saved in the default database or not?
Every SQLRecord object has an attribute ._state.db which can take the following values:
None: the object has not yet been saved to any database"default": the object is saved on the default database instance"account/name": the object is saved on a non-default database instance referenced byaccount/name(e.g.,laminlabs/lamindata)
The artifact has been transferred to the current database without feature & label annotations, but with updated data lineage:
artifact.describe()
Show code cell output
Artifact: example_datasets/mini_immuno/dataset1.h5ad (0000) | description: Flow cytometry readouts on invitro cell culture ├── uid: 9K1dteZ6Qx0EXK8g0000 run: NXf5FhV (__lamindb_transfer__/4XIuR0tvaiXM) │ kind: dataset otype: AnnData │ hash: FB3CeMjmg1ivN6HDy6wsSg size: 30.9 KB │ branch: main space: all │ created_at: 2025-07-29 12:27:25 UTC created_by: anonymous │ n_observations: 3 └── storage/path: s3://lamindata/.lamindb/9K1dteZ6Qx0EXK8g0000.h5ad
The data itself remained in the original storage location, which has been added to your default database’s storage location as a read-only location. This is indicated by the fact that the instance_uid does not match the uid of your default database.
ln.Storage.to_dataframe()
Show code cell output
| uid | root | description | type | region | instance_uid | is_locked | created_at | branch_id | created_on_id | space_id | created_by_id | run_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||
| 2 | D9BilDV2 | s3://lamindata | None | s3 | us-east-1 | 4XIuR0tvaiXM | False | 2023-04-22 05:50:06.537267+00:00 | 1 | 1 | 1 | 1 | 2.0 |
| 1 | 6hHdIA830qyP | /home/runner/work/lamindb/lamindb/docs/test-tr... | None | local | None | 1FHu5eE0uxm4 | False | 2026-03-06 16:22:41.246000+00:00 | 1 | 1 | 1 | 1 | NaN |
See the state of the database:
ln.view()
Show code cell output
****************
* module: core *
****************
Artifact
| uid | key | description | suffix | kind | otype | size | hash | n_files | n_observations | ... | is_latest | is_locked | created_at | branch_id | created_on_id | space_id | storage_id | run_id | schema_id | created_by_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||||||||||
| 1 | 9K1dteZ6Qx0EXK8g0000 | example_datasets/mini_immuno/dataset1.h5ad | Flow cytometry readouts on invitro cell culture | .h5ad | dataset | AnnData | 31672 | FB3CeMjmg1ivN6HDy6wsSg | None | 3 | ... | True | False | 2025-07-29 12:27:25.572900+00:00 | 1 | 1 | 1 | 2 | 2 | 1 | 1 |
1 rows × 21 columns
Run
| uid | name | description | entrypoint | started_at | finished_at | params | reference | reference_type | cli_args | ... | created_at | branch_id | created_on_id | space_id | transform_id | report_id | environment_id | plan_id | created_by_id | initiated_by_run_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||||||||||
| 2 | NXf5FhV73VGLfXDc | None | None | None | 2026-03-06 16:22:50.044000+00:00 | None | None | None | None | None | ... | 2026-03-06 16:22:50.044000+00:00 | 1 | 1 | 1 | 2 | None | None | None | 1 | 1.0 |
| 1 | 1fno97DClZA8Hf79 | None | None | None | 2026-03-06 16:22:45.161880+00:00 | None | None | None | None | None | ... | 2026-03-06 16:22:45.162000+00:00 | 1 | 1 | 1 | 1 | None | None | None | 1 | NaN |
2 rows × 21 columns
Schema
| uid | name | description | n_members | coerce | flexible | itype | otype | hash | minimal_set | ... | maximal_set | is_locked | is_type | created_at | branch_id | created_on_id | space_id | created_by_id | run_id | type_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||||||||||
| 1 | 0000000000000002 | anndata_ensembl_gene_ids_and_valid_features_in... | None | None | None | True | Composite | AnnData | UR_ozz2VI2sY8ckXop2RAg | True | ... | False | False | False | 2025-07-10 10:21:07.781328+00:00 | 1 | 1 | 1 | 1 | 2 | None |
1 rows × 21 columns
Storage
| uid | root | description | type | region | instance_uid | is_locked | created_at | branch_id | created_on_id | space_id | created_by_id | run_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||||
| 2 | D9BilDV2 | s3://lamindata | None | s3 | us-east-1 | 4XIuR0tvaiXM | False | 2023-04-22 05:50:06.537267+00:00 | 1 | 1 | 1 | 1 | 2.0 |
| 1 | 6hHdIA830qyP | /home/runner/work/lamindb/lamindb/docs/test-tr... | None | local | None | 1FHu5eE0uxm4 | False | 2026-03-06 16:22:41.246000+00:00 | 1 | 1 | 1 | 1 | NaN |
Transform
| uid | key | description | kind | source_code | hash | reference | reference_type | version_tag | is_latest | is_locked | created_at | branch_id | created_on_id | space_id | environment_id | plan_id | created_by_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| id | ||||||||||||||||||
| 2 | 4XIuR0tvaiXM0000 | __lamindb_transfer__/4XIuR0tvaiXM | Transfer from `laminlabs/lamindata` | function | None | None | None | None | None | True | False | 2026-03-06 16:22:50.039000+00:00 | 1 | 1 | 1 | None | None | 1 |
| 1 | qGqTBOkr0kO30000 | transfer.ipynb | Transfer data [
Show code cell output
! calling anonymously, will miss private instances
The transferred dataset is linked to a special type of transform that stores the slug and uid of the source instance:
artifact.transform.description
Show code cell output
'Transfer from `laminlabs/lamindata`'
The transform key has the form f"__lamindb_transfer__/{source_instance.uid}":
artifact.transform.key
Show code cell output
'__lamindb_transfer__/4XIuR0tvaiXM'
The current notebook run is linked as the initiated_by_run of the “transfer run”:
artifact.run.initiated_by_run.transform
Show code cell output
Transform(uid='qGqTBOkr0kO30000', version_tag=None, is_latest=True, key='transfer.ipynb', description='Transfer data [](https://github.com/laminlabs/lamindb/blob/main/docs/transfer.md)', kind='notebook', hash=None, reference=None, reference_type=None, environment=None, plan=None, branch_id=1, created_on_id=1, space_id=1, created_by_id=1, created_at=2026-03-06 16:22:45 UTC, is_locked=False)
Upon re-transferring a record, it will identify that the record already exists in the target database and simply map the record.
artifact = artifacts.get(key="example_datasets/mini_immuno/dataset1.h5ad")
artifact.save()
Show code cell output
→ mapped: Artifact(uid='9K1dteZ6Qx0EXK8g0000')
Artifact(uid='9K1dteZ6Qx0EXK8g0000', version_tag=None, is_latest=True, key='example_datasets/mini_immuno/dataset1.h5ad', description='Flow cytometry readouts on invitro cell culture', suffix='.h5ad', kind='dataset', otype='AnnData', size=31672, hash='FB3CeMjmg1ivN6HDy6wsSg', n_files=None, n_observations=3, branch_id=1, created_on_id=1, space_id=1, storage_id=2, run_id=2, schema_id=1, created_by_id=1, created_at=2025-07-29 12:27:25 UTC, is_locked=False)
If you also want to transfer annotations of the artifact, you can pass transfer="annotations" to save(). Just note that this might populate your target database with metadata that doesn’t match the conventions you want to enforce.
artifact = artifacts.get(key="example_datasets/mini_immuno/dataset1.h5ad")
artifact.save(transfer="annotations")
Show code cell output
→ mapped: Artifact(uid='9K1dteZ6Qx0EXK8g0000'), CellType(uid='ryEtgi1yGtAcX2'), CellType(uid='22LvKd01YyNA1a'), CellType(uid='6IC9NGJEv2Y4TD'), CellType(uid='ryEtgi1yGtAcX2'), ExperimentalFactor(uid='4WYv9kl0W2SroY')
→ transferred: Feature(uid='LIrjN9FbaLR1'), Feature(uid='xFdXre6ZPLlK'), Feature(uid='fJnNc4pzxe9c'), Feature(uid='7xDpJZiVLRl3'), Feature(uid='BaPfsAPgDFrT'), Feature(uid='DLeKfqUbrUsg'), Feature(uid='zvyDVbZln36o'), Feature(uid='Q8edF7CSgjG2'), Organism(uid='1dpCL6TduFJ3AP'), Source(uid='4BENqfHn'), Source(uid='404rkf5M'), Gene(uid='1j4At3x7akJU8n'), Gene(uid='6Aqvc8ckDYeNrD'), Gene(uid='3bhNYquOnA4sdo'), ULabel(uid='vmjLLqYy'), ULabel(uid='YAhFIvh5'), ULabel(uid='Yis4YLIB'), ULabel(uid='InLummy0'), Feature(uid='4ycwa8er0EB2'), Record(uid='ZRP07Y49Ni3Ne0Ae'), Record(uid='6pjoBrrz4f1EzQMO'), Record(uid='a6Zf73YeFR7o7RFU'), Record(uid='fNBzuANAusnkFv2p'), Schema(uid='JfgNiPmWNLZz4YRh'), Feature(uid='pNaJLQh8fRA6'), Project(uid='BZF49Wr2yZAC')
Artifact(uid='9K1dteZ6Qx0EXK8g0000', version_tag=None, is_latest=True, key='example_datasets/mini_immuno/dataset1.h5ad', description='Flow cytometry readouts on invitro cell culture', suffix='.h5ad', kind='dataset', otype='AnnData', size=31672, hash='FB3CeMjmg1ivN6HDy6wsSg', n_files=None, n_observations=3, branch_id=1, created_on_id=1, space_id=1, storage_id=2, run_id=2, schema_id=1, created_by_id=1, created_at=2025-07-29 12:27:25 UTC, is_locked=False)
The artifact is now annotated.
artifact.describe()
Show code cell output
Artifact: example_datasets/mini_immuno/dataset1.h5ad (0000) | description: Flow cytometry readouts on invitro cell culture ├── uid: 9K1dteZ6Qx0EXK8g0000 run: NXf5FhV (__lamindb_transfer__/4XIuR0tvaiXM) │ kind: dataset otype: AnnData │ hash: FB3CeMjmg1ivN6HDy6wsSg size: 30.9 KB │ branch: main space: all │ created_at: 2025-07-29 12:27:25 UTC created_by: anonymous │ n_observations: 3 ├── storage/path: s3://lamindata/.lamindb/9K1dteZ6Qx0EXK8g0000.h5ad ├── Dataset features │ ├── obs (8) │ │ assay_oid bionty.ExperimentalFactor.ontology… EFO:0008913 │ │ cell_type_by_expert bionty.CellType CD8-positive, alpha-beta T cell │ │ cell_type_by_model bionty.CellType B cell, T cell │ │ concentration str │ │ donor str │ │ perturbation ULabel DMSO, IFNG │ │ sample_note str │ │ treatment_time_h num │ └── var.T (3 bionty.Gene) │ CD14 num │ CD4 num │ CD8A num ├── External features │ └── experiment Record[scRNA-seq] EXP-scRNA-002 │ experiment ULabel Experiment 1 └── Labels └── .ulabels ULabel DMSO, IFNG, Experiment 1 .records Record EXP-scRNA-002 .projects Project Tutorials .cell_types bionty.CellType B cell, T cell, CD8-positive, alpha-be… .experimental_factors bionty.ExperimentalFactor single-cell RNA sequencing
# test the last 3 cells here
assert artifact.transform.description == "Transfer from `laminlabs/lamindata`"
assert artifact.transform.key == "__lamindb_transfer__/4XIuR0tvaiXM"
assert artifact.transform.uid == "4XIuR0tvaiXM0000"
assert artifact.run.initiated_by_run.transform.description.startswith("Transfer data")