A guide to getting your development environment set up for working with Tools for Experiments.
uv is a fast Python package and project manager written in Rust, developed by Astral (the team behind ruff). It serves as a drop-in replacement for pip, pip-tools, virtualenv, and more — but orders of magnitude faster.
Key concepts:
pyproject.toml: The single source of truth for your project's dependencies and metadata, following the modern Python packaging standard.uv.lock: A lockfile automatically generated by uv that pins exact versions of all dependencies (direct and transitive) for reproducible environments.- Editable installs: uv supports installing local packages in editable mode (
editable = true), meaning changes to the source code of those packages are immediately reflected without reinstalling. - Virtual environments: uv automatically creates and manages a
.venvin your project directory.
curl -LsSf https://astral.sh/uv/install.sh | shOr via pip:
pip install uvEach measurement or experiment folder should have a pyproject.toml that declares its dependencies. For packages that live locally on your machine (like instrumentserver or labcore), use [tool.uv.sources] to point uv to their local paths with editable installs:
[project]
name = "testing-uv-env" # (1) change to your project name
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"instrumentserver", # (2) list every package you need here
"labcore", # one string per package, comma-separated
]
[tool.uv.sources]
# (3) for each local package listed above, add an entry here pointing to its
# location on your machine. Paths are relative to this pyproject.toml file.
instrumentserver = { path = "../../github/instrumentserver", editable = true }
labcore = { path = "../../github/labcore", editable = true }What you need to change:
-
name— set it to something that identifies your experiment or measurement folder. -
dependencies— list all packages your code needs. Regular PyPI packages (e.g.numpy,matplotlib) just go here as plain strings and uv will fetch them automatically. Local packages also go here — they need a matching entry in[tool.uv.sources]. -
[tool.uv.sources]— for every local package independencies, add a line with the relative path from thispyproject.tomlto that package's root directory (the folder that contains its ownpyproject.tomlorsetup.py). Keepeditable = trueso that code changes in those repos take effect immediately.
For example, if your experiment folder is at ~/projects/my-experiment/ and labcore is cloned at ~/github/labcore/, the relative path would be ../../github/labcore.
From the directory containing your pyproject.toml, run:
uv syncThis will:
- Create a
.venvvirtual environment in the current directory (if it doesn't exist). - Install all dependencies listed in
pyproject.toml. - Install the local editable packages from the paths defined in
[tool.uv.sources]. - Generate or update
uv.lock.
source .venv/bin/activateOr run commands directly without activating:
uv run python my_script.py
uv run jupyter labuv does not automatically register your virtual environment as a Jupyter kernel. This is by design — uv manages only the environment itself, not the kernel registry that Jupyter uses to discover Python environments. As a result, even after running uv sync, your environment will not appear in JupyterLab's kernel picker until you register it manually.
To register it, first make sure ipykernel is installed in the environment, then use it to add the kernel to Jupyter's registry:
uv add ipykernel
uv run python -m ipykernel install --user --name my-experiment --display-name "My Experiment"--nameis a short identifier used internally (no spaces).--display-nameis what appears in the JupyterLab UI.
After running this, restart JupyterLab and the kernel will be available in the launcher and the kernel picker.
To list all registered kernels:
uv run jupyter kernelspec listTo remove a kernel you no longer need:
uv run jupyter kernelspec remove my-experimentuv add some-packageThis updates pyproject.toml and uv.lock automatically.
conda is a cross-platform package and environment manager. mamba is a faster drop-in replacement for conda that uses the same commands and environment files.
-
Miniforge (recommended — ships with mamba by default): Download from github.com/conda-forge/miniforge and follow the installer instructions.
-
Miniconda (conda only): Download from docs.conda.io/en/latest/miniconda.html.
A base environment.yml is provided at the root of this repository with a standard set of dependencies:
name: labcore
channels:
- conda-forge
- defaults
dependencies:
- python=3.10
- jupyterlab
- jupyter_bokeh
- qcodes=0.44.1
- bokeh
- pandas
- xarray
- matplotlib
- numpy=1.26.4
- scipy
- scikit-learn
- seaborn
- lmfit
- h5py=3.10.0
- xhistogram
- holoviews
- panel
- param
- hvplot
- versioningit
- qtpy
- pip
- gitpython
- watchdog
- pywaveletsTo create the environment from it, run from the root of the repository:
conda env create -f environment.yml
conda activate labcoreWith mamba (faster):
mamba env create -f environment.yml
mamba activate labcoreIf you need extra packages not in environment.yml, install them into the active environment:
conda install -c conda-forge some-packageFor packages only available on PyPI:
pip install some-packageFor local repositories like instrumentserver or labcore, install them in editable mode using pip. Replace the paths below with the actual location of each repo on your machine:
pip install -e /path/to/instrumentserver
pip install -e /path/to/labcoreFor example, if your repos live in ~/github/:
pip install -e ~/github/instrumentserver
pip install -e ~/github/labcoreThe -e flag means editable — any changes you make to the source code of those packages are immediately active without needing to reinstall.
To export your environment so others can reproduce it:
conda env export > environment.ymlTo recreate it from the file:
conda env create -f environment.ymlFor a more portable export (cross-platform, without build strings):
conda env export --no-builds > environment.yml