Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Hamilton STAR
=============

Installation
------------

.. code-block:: bash

pip install pylabrobot[usb]

See :ref:`using-the-usb-interface` for platform-specific driver setup (libusb on Mac, Zadig on Windows).

Tools for working with Hamilton-STAR specific functions.

.. toctree::
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Cole Parmer Masterflex

## Installation

```bash
pip install pylabrobot[serial]
```

PyLabRobot supports the following pumps:

- {ref}`Cole Parmer Masterflex <masterflex>`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Heater Shakers

## Installation

Most heater-shakers use a serial connection:

```bash
pip install pylabrobot[serial]
```

For Inheco devices in HID mode, install `pip install pylabrobot[hid]` instead.

Heater-shakers are a hybrid of {class}`~pylabrobot.temperature_controllers.temperature_controller.TemperatureController` and {class}`~pylabrobot.shakers.shaker.Shaker`. They are used to control the temperature of a sample while shaking it.

PyLabRobot supports the following heater shakers:
Expand Down
6 changes: 6 additions & 0 deletions docs/user_guide/01_material-handling/sealers/sealers.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Sealers

## Installation

```bash
pip install pylabrobot[serial]
```

In automated wet lab workflows, **microplate sealers** are essential for preserving sample integrity.
They prevent **evaporation**, **cross-contamination**, and **spillage**, especially during heating, shaking, storage, or robotic transport.

Expand Down
6 changes: 6 additions & 0 deletions docs/user_guide/01_material-handling/tilting.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Tilting

## Installation

```bash
pip install pylabrobot[serial]
```

Currently only the Hamilton tilt module is supported.

```python
Expand Down
8 changes: 2 additions & 6 deletions docs/user_guide/02_analytical/plate-reading/synergyh1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Synergy H1\n",
"\n",
"Synergy H1 is an Agilent BioTek microplate reader that can read absorbance, fluorescence, and luminescence. Please refer to the [user guide](https://cqls.oregonstate.edu/sites/cqls.oregonstate.edu/files/synergy_h1_user_manual_sd-xb000426.pdf) for installation instructions."
]
"source": "# Synergy H1\n\n## Installation\n\n```bash\npip install pylabrobot[ftdi]\n```\n\nSynergy H1 is an Agilent BioTek microplate reader that can read absorbance, fluorescence, and luminescence. Please refer to the [user guide](https://cqls.oregonstate.edu/sites/cqls.oregonstate.edu/files/synergy_h1_user_manual_sd-xb000426.pdf) for installation instructions."
},
{
"cell_type": "code",
Expand Down Expand Up @@ -286,4 +282,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
}
}
34 changes: 18 additions & 16 deletions docs/user_guide/_getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

These instructions describe how to install PyLabRobot.

Note that there are additional installation steps for using the firmware (universal) interface to Hamiltons and Tecans, see {ref}`below <using-the-firmware-interface>`.
Note that there are additional installation steps for using the USB interface to Hamiltons and Tecans, see {ref}`below <using-the-usb-interface>`.

## Installing PyLabRobot

Expand Down Expand Up @@ -49,21 +49,23 @@ pip install "pylabrobot[testing]"

There's a multitude of other optional dependencies that you can install. Replace `[docs]` with one of the following items to install the desired dependencies.

- `fw`: Needed for firmware control over Hamilton robots.
- `http`: Needed for the HTTP backend.
- `websockets`: Needed for the WebSocket backend.
- `simulation`: Needed for the simulation backend.
- `opentrons`: Needed for the Opentrons backend.
- `agrow`: Needed for the AgrowPumpArray backend.
- `plate_reading`: Needed to interact with the CLARIO Star plate reader.
- `inheco`: Needed for the Inheco backend.
- `dev`: Everything you need for development.
- `all`: Everything. May not be available on all platforms.
| Group | Packages | When you need it |
|-------|----------|-----------------|
| `serial` | pyserial | Serial devices: BioShake, Cytomat, Inheco (serial mode), Hamilton Tilt Module, Cole Parmer Masterflex, A4S Sealer, XPeel Peeler |
| `usb` | pyusb, libusb-package | USB devices: Hamilton STAR/STARlet, Tecan EVO (firmware) |
| `ftdi` | pylibftdi, pyusb | FTDI devices: BioTek Synergy H1 plate reader |
| `hid` | hid | HID devices: Inheco Incubator/Shaker (HID mode) |
| `modbus` | pymodbus | Modbus devices: Agrow Pump Array |
| `http` | requests | HTTP-based backends |
| `websockets` | websockets | WebSocket backend |
| `opentrons` | opentrons-http-api-client | Opentrons backend |
| `gui` | flask | PyLabRobot GUI |
| `dev` | All of the above + testing/linting tools | Development |

To install multiple dependencies, separate them with a comma:

```bash
pip install 'pylabrobot[fw,http]'
pip install 'pylabrobot[serial,usb]'
```

Or install all dependencies at once:
Expand All @@ -72,16 +74,16 @@ Or install all dependencies at once:
pip install 'pylabrobot[all]'
```

(using-the-firmware-interface)=
(using-the-usb-interface)=

## Using the firmware interface with Hamilton or Tecan robots
## Using the USB interface with Hamilton or Tecan robots

If you want to use the firmware version of the Hamilton or Tecan interfaces, you need to install a backend for [PyUSB](https://github.com/pyusb/pyusb/). You can find the official installation instructions [here](https://github.com/pyusb/pyusb#requirements-and-platform-support). The following is a complete (and probably easier) guide for macOS, Linux and Windows.

Reminder: when you are using the firmware version, make sure to install the firmware dependencies as follows:
First, install the USB dependencies:

```bash
pip install pylabrobot[fw]
pip install pylabrobot[usb]
```

### On Linux
Expand Down
10 changes: 8 additions & 2 deletions pylabrobot/io/ftdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,16 @@ def __init__(
):
if not HAS_PYLIBFTDI:
global _FTDI_ERROR
raise RuntimeError(f"pylibftdi not installed. Import error: {_FTDI_ERROR}")
raise RuntimeError(
"pylibftdi is not installed. Install with: pip install pylabrobot[ftdi]. "
f"Import error: {_FTDI_ERROR}"
)
if not HAS_PYUSB:
global _PYUSB_ERROR
raise RuntimeError(f"pyusb not installed. Import error: {_PYUSB_ERROR}")
raise RuntimeError(
"pyusb is not installed. Install with: pip install pylabrobot[ftdi]. "
f"Import error: {_PYUSB_ERROR}"
)

self._device_id = device_id
self._vid = vid
Expand Down
4 changes: 2 additions & 2 deletions pylabrobot/io/hid.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ async def setup(self):
"""
if not USE_HID:
raise RuntimeError(
"This backend requires the `hid` package to be installed."
f" Import error: {_HID_IMPORT_ERROR}"
"hid is not installed. Install with: pip install pylabrobot[hid]. "
f"Import error: {_HID_IMPORT_ERROR}"
)

# --- 1. Enumerate all HID devices ---
Expand Down
5 changes: 4 additions & 1 deletion pylabrobot/io/serial.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ async def setup(self):
"""

if not HAS_SERIAL:
raise RuntimeError(f"pyserial not installed. Import error: {_SERIAL_IMPORT_ERROR}")
raise RuntimeError(
"pyserial is not installed. Install with: pip install pylabrobot[serial]. "
f"Import error: {_SERIAL_IMPORT_ERROR}"
)

loop = asyncio.get_running_loop()
self._executor = ThreadPoolExecutor(max_workers=1)
Expand Down
4 changes: 2 additions & 2 deletions pylabrobot/io/usb.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ async def setup(self):

if not USE_USB:
raise RuntimeError(
f"USB dependencies could not be imported due to the following error: {_USB_IMPORT_ERROR}. "
"Please install pyusb and libusb. "
"pyusb/libusb is not installed. Install with: pip install pylabrobot[usb]. "
f"Import error: {_USB_IMPORT_ERROR}. "
"https://docs.pylabrobot.org/installation.html"
)

Expand Down
2 changes: 1 addition & 1 deletion pylabrobot/pumps/agrowpumps/agrowdosepump_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async def setup(self):
async def _setup_modbus(self):
if AsyncModbusSerialClient is None:
raise RuntimeError(
"pymodbus is not installed. Please install it with 'pip install pymodbus'."
"pymodbus is not installed. Install with: pip install pylabrobot[modbus]."
f" Import error: {_MODBUS_IMPORT_ERROR}"
)
self._modbus = AsyncModbusSerialClient(
Expand Down
35 changes: 18 additions & 17 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@ dynamic = ["version"]
dependencies = ["typing_extensions==4.15.0"]

[project.optional-dependencies]
fw = ["pyserial==3.5", "pyusb==1.3.1", "libusb-package==1.0.26.1"]
serial = ["pyserial==3.5"]
usb = ["pyusb==1.3.1", "libusb-package==1.0.26.1"]
ftdi = ["pylibftdi==0.23.0", "pyusb==1.3.1"]
hid = ["hid==1.0.8"]
modbus = ["pymodbus==3.6.8"]
http = ["requests==2.32.5", "types-requests==2.32.4.20250913"]
plate_reading = ["pylibftdi==0.23.0"]
websockets = ["websockets==15.0.1"]
visualizer = ["websockets==15.0.1"]
opentrons = ["opentrons-http-api-client"]
inheco = ["hid==1.0.8"]
agrow = ["pymodbus==3.6.8"]
gui = ["flask[async]==3.1.2"]
dev = [
"PyLabRobot[fw,http,plate_reading,websockets,visualizer,opentrons,inheco,agrow,gui]",
"PyLabRobot[serial,usb,ftdi,hid,modbus,http,websockets,visualizer,opentrons,gui]",
"pytest==8.4.2",
"pytest-timeout==2.4.0",
"mypy==1.18.2",
Expand Down Expand Up @@ -70,23 +71,23 @@ python = ">=3.9"
[tool.pixi.pypi-dependencies]
pylabrobot = { path = ".", editable = true }

[tool.pixi.feature.fw.dependencies]
[tool.pixi.feature.usb.dependencies]
libusb = "*"

[tool.pixi.feature.fw.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["fw"] }
[tool.pixi.feature.usb.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["usb"] }

[tool.pixi.feature.plate-reading.dependencies]
[tool.pixi.feature.ftdi.dependencies]
libftdi = "*"

[tool.pixi.feature.plate-reading.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["plate_reading"] }
[tool.pixi.feature.ftdi.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["ftdi"] }

[tool.pixi.feature.inheco.dependencies]
[tool.pixi.feature.hid.dependencies]
libhidapi = "*"

[tool.pixi.feature.inheco.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["inheco"] }
[tool.pixi.feature.hid.pypi-dependencies]
pylabrobot = { path = ".", editable = true, extras = ["hid"] }

[tool.pixi.feature.dev.dependencies]
libusb = "*"
Expand All @@ -105,7 +106,7 @@ typecheck = "python -m mypy pylabrobot --check-untyped-defs"

[tool.pixi.environments]
default = { solve-group = "default" }
fw = { features = ["fw"], solve-group = "fw" }
plate-reading = { features = ["plate-reading"], solve-group = "plate-reading" }
inheco = { features = ["inheco"], solve-group = "inheco" }
usb = { features = ["usb"], solve-group = "usb" }
ftdi = { features = ["ftdi"], solve-group = "ftdi" }
hid = { features = ["hid"], solve-group = "hid" }
dev = { features = ["dev"], solve-group = "dev" }