Skip to content
Merged
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
24 changes: 24 additions & 0 deletions docs/user_guide/01_material-handling/centrifuge/_centrifuge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Centrifuges

Centrifuges are controlled by the {class}`~pylabrobot.centrifuge.centrifuge.Centrifuge` class. This class takes a backend as an argument. The backend is responsible for communicating with the centrifuge and is specific to the hardware being used.

The {class}`~pylabrobot.centrifuge.centrifuge.Centrifuge` class has a number of methods for controlling the centrifuge. These are:

- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.open_door`: Open the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.close_door`: Close the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.lock_door`: Lock the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.unlock_door`: Unlock the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.lock_bucket`: Lock centrifuge buckets.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.unlock_bucket`: Unlock centrifuge buckets.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.go_to_bucket1`: Rotate to Bucket 1.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.go_to_bucket2`: Rotate to Bucket 2.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.rotate_distance`: Rotate the buckets a specified distance (8000 = 360 degrees).
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.start_spin_cycle`: Start centrifuge spin cycle.

PLR supports the following centrifuges:

```{toctree}
:maxdepth: 1

agilent_vspin
```

This file was deleted.

179 changes: 71 additions & 108 deletions docs/user_guide/01_material-handling/centrifuge/agilent_vspin.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,95 @@
# Agilent VSpin

PyLabRobot supports the following centrifuges:

- {ref}`VSpin <VSpin>`

Centrifuges are controlled by the {class}`~pylabrobot.centrifuge.centrifuge.Centrifuge` class. This class takes a backend as an argument. The backend is responsible for communicating with the centrifuge and is specific to the hardware being used.
The VSpin centrifuge is controlled by the {class}`~pylabrobot.centrifuge.vspin_backend.VSpinBackend` class.

```python
from pylabrobot.centrifuge import Centrifuge
backend = SomeCentrifugeBackend()
pr = Centrifuge(backend=backend)
await pr.setup()
from pylabrobot.centrifuge import Centrifuge, VSpinBackend
await cf.setup()
cf = Centrifuge(name = "centrifuge", backend = VSpinBackend(device_id="YOUR_FTDI_ID_HERE"), size_x= 1, size_y=1, size_z=1)
```

The {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.setup` method is used to initialize the centrifuge. This is where the backend will connect to the centrifuge and perform any necessary initialization.
You need to calibrate the bucket 1 position for every vspin. You can do that by opening the door (`cf.open_door()`), manually rotating the buckets to align bucket 1 with the door, and then setting bucket 1 position to the current position with `cf.backend.set_bucket_1_position_to_current()`. This will save the calibration for the current centrifuge to disk (based on the usb serial number).

The {class}`~pylabrobot.centrifuge.centrifuge.Centrifuge` class has a number of methods for controlling the centrifuge. These are:

- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.open_door`: Open the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.close_door`: Close the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.lock_door`: Lock the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.unlock_door`: Unlock the centrifuge door.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.lock_bucket`: Lock centrifuge buckets.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.unlock_bucket`: Unlock centrifuge buckets.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.go_to_bucket1`: Rotate to Bucket 1.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.go_to_bucket2`: Rotate to Bucket 2.
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.rotate_distance`: Rotate the buckets a specified distance (8000 = 360 degrees).
- {meth}`~pylabrobot.centrifuge.centrifuge.Centrifuge.start_spin_cycle`: Start centrifuge spin cycle.
```python
await cf.open_door()
# Manually rotate buckets to align bucket 1 with door
await cf.backend.set_bucket_1_position_to_current()
```

Start spin cycle:

```python
await cf.start_spin_cycle(g = 800, duration = 60)
```

(VSpin)=
Going to buckets:

## VSpin
```python
await cf.go_to_bucket1()
await cf.go_to_bucket2()
```

The VSpin centrifuge is controlled by the {class}`~pylabrobot.centrifuge.vspin_backend.VSpinBackend` class.
## Loader

The VSpin can optionally be used with a loader (called Access2). The loader is optional because you can also use a robotic arm like an iSWAP to move a plate directly into the centrifuge.

Here's how to use the loader:

```python
from pylabrobot.centrifuge import Centrifuge, VSpinBackend
cf = Centrifuge(name = 'centrifuge', backend = VSpinBackend(bucket_1_position=0), size_x= 1, size_y=1, size_z=1)
import asyncio

from pylabrobot.centrifuge import Access2, VSpinBackend
v = VSpinBackend(device_id="YOUR_VSPIN_FTDI_ID_HERE")
centrifuge, loader = Access2(name="name", vspin=v, device_id="YOUR_LOADER_FTDI_ID_HERE")

# initialize the centrifuge and loader in parallel
await asyncio.gather(
centrifuge.setup(),
loader.setup()
)

# go to a bucket and open the door before loading
await centrifuge.go_to_bucket1()
await centrifuge.open_door()

# assign a plate to the loader before loading. This can also be done implicitly by for example
# lh.move_plate(plate, loader)
from pylabrobot.resources import Cor_96_wellplate_360ul_Fb
plate = Cor_96_wellplate_360ul_Fb(name="plate")
loader.assign_child_resource(plate)

# load and unload the plate
await loader.load()
await loader.unload()
```

### Installation
## Installation

The VSpin centrifuge connects to your system via a COM port. Integrating it with `pylabrobot` library requires some setup. Follow this guide to get started.

#### 1. Preparing Your Environment
### 1. Installing libftdi

- Windows:
#### macOS

##### Find Your Python Directory
Install libftdi using [Homebrew](https://brew.sh/):

```bash
brew install libftdi
```

#### Linux

Debian (rpi) / Ubuntu etc:

```bash
sudo apt-get install libftdi-dev
```

Other distros have similar packages.

#### Windows

**Find Your Python Directory**

To use the necessary FTDI `.dll` files, you need to locate your Python environment:

Expand All @@ -66,7 +102,7 @@ To use the necessary FTDI `.dll` files, you need to locate your Python environme
2. This will print a path, e.g., `C:\Python39\python.exe`.
3. Navigate to the `Scripts` folder in the same directory as `python.exe`.

##### **Download FTDI DLLs**
**Download FTDI DLLs**

Download the required `.dll` files from the following link:
[FTDI Development Kit](https://sourceforge.net/projects/picusb/files/libftdi1-1.5_devkit_x86_x64_19July2020.zip/download) (link will start download).
Expand All @@ -77,31 +113,11 @@ Download the required `.dll` files from the following link:
- `libftdi1.dll`
- `libusb-1.0.dll`

##### Place DLLs in Python Scripts Folder
**Place DLLs in Python Scripts Folder**

Paste the copied `.dll` files into the `Scripts` folder of your Python environment. This enables Python to communicate with FTDI devices.

- macOS:

Install libftdi using [Homebrew](https://brew.sh/):

```bash
brew install libftdi
```

- Linux:

Debian (rpi) / Ubuntu etc:

```bash
sudo apt-get install libftdi-dev
```

Other distros may have similar packages.

#### 2. Configuring the Driver with Zadig

- **This step is only required on Windows.**
**Configuring the Driver with Zadig**

Use Zadig to replace the default driver of the VSpin device with `libusbk`:

Expand All @@ -118,7 +134,7 @@ Use Zadig to replace the default driver of the VSpin device with `libusbk`:

> **Note:** If you need to revert to the original driver for tools like the Agilent Centrifuge Config Tool, go to **Device Manager** and uninstall the `libusbk` driver. The default driver will reinstall automatically.

#### 3. Finding the FTDI ID
### 2. Finding the FTDI ID

To interact with the centrifuge programmatically, you need its FTDI device ID. Use the following steps to find it:

Expand All @@ -132,57 +148,4 @@ To interact with the centrifuge programmatically, you need its FTDI device ID. U
```
3. Copy the ID (`FTE0RJ5T` or your equivalent).

#### **4. Setting Up the Centrifuge**

Use the following code to configure the centrifuge in Python:

```python
from pylabrobot.centrifuge import Centrifuge, VSpinBackend

# Replace with your specific FTDI device ID and bucket position for profile in Agilent Centrifuge Config Tool.
backend = VSpinBackend(bucket_1_position=6969, device_id="XXXXXXXX")
centrifuge = Centrifuge(
backend=backend,
name="centrifuge",
size_x=1, size_y=1, size_z=1
)

# Initialize the centrifuge.
await centrifuge.setup()
```

You’re now ready to use your VSpin centrifuge with `pylabrobot`!

### Loader

The VSpin can optionally be used with a loader (called Access2). The loader is optional because you can also use a robotic arm like an iSWAP to move a plate directly into the centrifuge.

Here's how to use the loader:

```python
import asyncio

from pylabrobot.centrifuge import Access2, VSpinBackend
v = VSpinBackend(device_id="FTE1YWTI", bucket_1_position=1314) # bucket 1 position is empirically determined
centrifuge, loader = Access2(name="name", vspin=v, device_id="FTE1YZC5")

# initialize the centrifuge and loader in parallel
await asyncio.gather(
centrifuge.setup(),
loader.setup()
)

# go to a bucket and open the door before loading
await centrifuge.go_to_bucket1()
await centrifuge.open_door()

# assign a plate to the loader before loading. This can also be done implicitly by for example
# lh.move_plate(plate, loader)
from pylabrobot.resources import Cor_96_wellplate_360ul_Fb
plate = Cor_96_wellplate_360ul_Fb(name="plate")
loader.assign_child_resource(plate)

# load and unload the plate
await loader.load()
await loader.unload()
```
Loading