Skip to main content

daisylab

Python library for controlling Daisy laboratory instruments over USB serial.

daisylab discovers Daisy hardware on your serial ports, validates the connected instruments against what your code expects, and gives you a clean, per-instrument API for pumps, valves, and motion stages — with background threads handling the serial protocol for you.

Installation

pip install daisylab

Requires Python 3.9+ and pyserial 3.5+.

Quick start

import daisylab

with daisylab.connect() as lab:
    print("Found ports:", lab.ports)
    print("Instrument types:", lab.instruments_list)

    # Declare the instruments on a port, in physical order, by type code.
    group = daisylab.InstrumentGroup([10, 2])   # Peri T + Rotary Valve
    lab.add_group(group)

    pump  = group.inst[0]   # DaisyPeriT
    valve = group.inst[1]   # DaisyRotaryValve

    valve.home()
    pump.run(speed=50.0, volume=10.0, wait=True)   # 50 ml/min, 10 ml
    valve.select_port(3, wait=True)

connect() returns a DaisyInterface (usable as a context manager). Each InstrumentGroup is bound to a serial port in the order you call add_group().

Supported instruments

Instruments are declared by integer type code (the value the firmware reports during roll-call) or by a case-insensitive name substring such as "Peri T" or "gantry".

Code Class Hardware
1 DaisyPeriS Peri pump S
2 DaisyRotaryValve 12-port rotary valve, 0.032″ orifice
3 DaisySolVal Solenoid valve array (≤8)
4 DaisyPistonPump Piston pump (1 ml)
5 DaisyPeriPumpXL Peri pump XL
6 DaisyRotaryValveXL 12-port rotary valve, 0.052″ orifice
7 DaisySolValXL Solenoid valve array XL
8 DaisyGantry XY Cartesian stage
9 DaisyZStage Z linear stage
10 DaisyPeriT Peri pump T (6-roller)
11 DaisyPeriP Peri pump P
12 DaisyPistonPump Piston pump (5 ml)
13 DaisyProcess Multi-channel pH/sensor
14 DaisyMasterflow Dual-channel mass flow controller (alias DaisyMFC)
15 DaisyPeriT3Roller Peri pump T, 3-roller
16 DaisyPistonPump Piston pump (100 µl)
17 DaisyRotaryValve096 12-port rotary valve, 0.096″ orifice

Codes are assigned by the firmware Instrument ID registry and are never renumbered; a retired model leaves a gap. The ID is a uint16_t; 0 and 65535 (unconfigured / safe mode) are reserved, never assigned, and each reports its own distinct error.

The rotary valve is one product in three bores: DaisyRotaryValve032 / 052 / 096 are the canonical classes, each with an ORIFICE attribute, and DaisyRotaryValve / DaisyRotaryValveXL remain as aliases of the 0.032″ and 0.052″ builds.

Peristaltic pump speed limits

Peri pumps enforce a per-model maximum motor speed. run(speed, volume) converts the requested flow (ml/min) to RPM using the current calibration and raises ValueError before sending anything if it would exceed the cap:

Model Max RPM
Peri S / Peri P 150
Peri T / Peri Pump XL 300

The cap is calibration-aware: recalibrating the tubing shifts the ml/min ceiling but the motor is always held to its rated RPM.

Recalibrate after upgrading. The rev/s → firmware-speed constant was corrected from an empirical 1.45 to the datasheet value 1.398101 (2**24 / 12 MHz). Every peristaltic previously ran about 3.7% fast, so a calibration measured on an older release now delivers about 3.7% low. Re-run calibrate() (or calibrate_by_tubing()) on each pump.

Piston pump speed limits

The cap is derived from the syringe at the head's 54 strokes/min rating:

Model Max speed (µl/min)
100 µl 5,400
1 ml 54,000
5 ml 200,000

The 5 ml build is the exception to the rule, which would give 270,000. Above roughly 6.85 rev/s its dispense stroke stalls the motor at nameplate current, and firmware rejects anything faster — so 200,000 is the achievable rating rather than the nameplate one. run() raises DaisyValueError if exceeded.

Examples

Standalone, runnable scripts live in daisylab/examples/:

  • daisy_controller.py — universal interactive controller for any instrument
  • z_stage_controller.py — interactive Z-stage controller
  • z_stage_peri_t_sequence.py — automated dispense sequence (home → lower → pump → raise)

Each supports a --demo flag that runs against simulated hardware (no serial I/O required):

python daisylab/examples/daisy_controller.py --demo

A sample Jupyter notebook is also included in the package at daisylab/jupyter/sample.ipynb. After installing, you can find it at <site-packages>/daisylab/jupyter/sample.ipynb.

Exceptions

Every error the library raises derives from DaisyError, so a single except daisylab.DaisyError is a complete catch-all for any instrument:

  • DaisyTimeoutError — no OK / a BAD reply within the timeout
  • DaisyConnectionError — no devices found / connection failure
  • DaisyInstrumentMismatchError — software list ≠ hardware roll-call
  • DaisyValueError — invalid argument or value (e.g. speed above a pump's MAX_RPM, unknown type code, malformed device response). Also subclasses the built-in ValueError, so existing except ValueError handlers keep working.

Stopping safely

stop_all() halts every instrument across all groups (best-effort — one instrument's failure won't block the others); ports stay open so you can recover. safe_session() wraps a command sequence and stops everything if any exception propagates:

with lab.safe_session():
    pump.run(speed=50, volume=10, wait=True)
    gantry.run(100, 150, wait=True)   # if this raises, the pump is stopped
# the original exception is re-raised after the stop

lab.stop_all()          # or halt everything manually (alias: lab.emergency_stop())
group.stop_all()        # or just one group

Development

git clone https://github.com/ScalablesLab/daisy-python-library
cd daisy-python-library
pip install -e ".[test]"
pytest

The test suite is hardware-free — tests/fakes.py provides a synchronous FakeSerialManager that synthesises device replies, so the real drivers run end to end without any instruments attached.

License

Apache License 2.0 — see LICENSE. Copyright Scalables, LLC.

Release files for daisylab 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for daisylab 1.1.1
File Interpreter ABI Platform
daisylab-1.1.1-cp314-cp314-macosx_11_0_x86_64.whl CPython 3.14 CPython 3.14 macOS 11.0+ x86-64 Details
daisylab-1.1.1-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details

Total release size: 1.9 MB

Release files / daisylab-1.1.1-cp314-cp314-macosx_11_0_x86_64.whl

Download URL daisylab-1.1.1-cp314-cp314-macosx_11_0_x86_64.whl
Size 966.1 kB
Tags CPython 3.14 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
4851562c5d49b41146fdb7c5d786a1a1d5561f431dd877983140c095df6f95a9
BLAKE2b-256 checksum
How to use checksums
f4242723c225ca4cbee9237727549cba3fcd6915ed188be4c7c483eb937527d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / daisylab-1.1.1-cp314-cp314-macosx_11_0_arm64.whl

Download URL daisylab-1.1.1-cp314-cp314-macosx_11_0_arm64.whl
Size 923.0 kB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
fa662de5d78b29276ed7e9a5c2d81a524e00b41c2cba0275fe4e468bd2081999
BLAKE2b-256 checksum
How to use checksums
dd77c8475a2c655d972d429cc8bdc00aac229c0a6775899340762bbfb34315fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

1.2.0

2 release files

This release

1.1.1 This release

2 release files

1.1.0

2 release files

0.6.0

18 release files

0.5.0

18 release files

0.4.0

18 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page