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.0

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.0
File Interpreter ABI Platform
daisylab-1.1.0-cp314-cp314-macosx_11_0_x86_64.whl CPython 3.14 CPython 3.14 macOS 11.0+ x86-64 Details
daisylab-1.1.0-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.0-cp314-cp314-macosx_11_0_x86_64.whl

Download URL daisylab-1.1.0-cp314-cp314-macosx_11_0_x86_64.whl
Size 964.9 kB
Tags CPython 3.14 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
bf34e2b90f1dfef50439d88f07aa3c03fb8309a82579bfa5f37abc1f9ea4813a
BLAKE2b-256 checksum
How to use checksums
027d8d4b43d9f00ebf130caeeaab7cae3f846a7271e0daa121d25613bbe2e553
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.0-cp314-cp314-macosx_11_0_arm64.whl

Download URL daisylab-1.1.0-cp314-cp314-macosx_11_0_arm64.whl
Size 921.4 kB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
55110a1af81521b60c9e78b6df2bfb4e67d49bc7c2e01e8580ffaea009c62a40
BLAKE2b-256 checksum
How to use checksums
3d17650e95ebb206327127215fc8454d88ce0501e903f011fa0d85b1493cff49
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

This release

1.1.0 This release

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