Setting Up Your Environment#

A guide to getting your development environment set up for working with Tools for Experiments.


Option 1: Using uv#

What is uv?#

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 .venv in your project directory.

Installing uv#

curl -LsSf https://astral.sh/uv/install.sh | sh

Or via pip:

pip install uv

Project structure: pyproject.toml#

Each 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:

  1. name — set it to something that identifies your experiment or measurement folder.

  2. 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].

  3. [tool.uv.sources] — for every local package in dependencies, add a line with the relative path from this pyproject.toml to that package’s root directory (the folder that contains its own pyproject.toml or setup.py). Keep editable = true so 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.

Creating and syncing the environment#

From the directory containing your pyproject.toml, run:

uv sync

This will:

  1. Create a .venv virtual environment in the current directory (if it doesn’t exist).

  2. Install all dependencies listed in pyproject.toml.

  3. Install the local editable packages from the paths defined in [tool.uv.sources].

  4. Generate or update uv.lock.

Activating the environment#

source .venv/bin/activate

Or run commands directly without activating:

uv run python my_script.py
uv run jupyter lab

Registering the environment as a Jupyter kernel#

uv 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"
  • --name is a short identifier used internally (no spaces).

  • --display-name is 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 list

To remove a kernel you no longer need:

uv run jupyter kernelspec remove my-experiment

Adding new dependencies#

uv add some-package

This updates pyproject.toml and uv.lock automatically.


Option 2: Using conda / mamba#

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.

Installing conda or mamba#

Creating an environment from the provided file#

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
  - pywavelets

To create the environment from it, run from the root of the repository:

conda env create -f environment.yml
conda activate labcore

With mamba (faster):

mamba env create -f environment.yml
mamba activate labcore

Adding or changing dependencies#

If you need extra packages not in environment.yml, install them into the active environment:

conda install -c conda-forge some-package

For packages only available on PyPI:

pip install some-package

Installing local packages in editable mode#

For 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/labcore

For example, if your repos live in ~/github/:

pip install -e ~/github/instrumentserver
pip install -e ~/github/labcore

The -e flag means editable — any changes you make to the source code of those packages are immediately active without needing to reinstall.

Exporting and sharing your environment#

To export your environment so others can reproduce it:

conda env export > environment.yml

To recreate it from the file:

conda env create -f environment.yml

For a more portable export (cross-platform, without build strings):

conda env export --no-builds > environment.yml