Files
gh-k-dense-ai-claude-scient…/skills/pylabrobot/references/analytical-equipment.md
2025-11-30 08:30:10 +08:00

465 lines
12 KiB
Markdown

# Analytical Equipment in PyLabRobot
## Overview
PyLabRobot integrates with analytical equipment including plate readers, scales, and other measurement devices. This allows automated workflows that combine liquid handling with analytical measurements.
## Plate Readers
### BMG CLARIOstar (Plus)
The BMG Labtech CLARIOstar and CLARIOstar Plus are microplate readers that measure absorbance, luminescence, and fluorescence.
#### Hardware Setup
**Physical Connections:**
1. IEC C13 power cord to mains power
2. USB-B cable to computer (with security screws on device end)
3. Optional: RS-232 port for plate stacking units
**Communication:**
- Serial connection through FTDI/USB-A at firmware level
- Cross-platform support (Windows, macOS, Linux)
#### Software Setup
```python
from pylabrobot.plate_reading import PlateReader
from pylabrobot.plate_reading.clario_star_backend import CLARIOstarBackend
# Create backend
backend = CLARIOstarBackend()
# Initialize plate reader
pr = PlateReader(
name="CLARIOstar",
backend=backend,
size_x=0.0, # Physical dimensions not critical for plate readers
size_y=0.0,
size_z=0.0
)
# Setup (initializes device)
await pr.setup()
# When done
await pr.stop()
```
#### Basic Operations
**Opening and Closing:**
```python
# Open loading tray
await pr.open()
# (Load plate manually or robotically)
# Close loading tray
await pr.close()
```
**Temperature Control:**
```python
# Set temperature (in Celsius)
await pr.set_temperature(37)
# Note: Reaching temperature is slow
# Set temperature early in protocol
```
**Reading Measurements:**
```python
# Absorbance reading
data = await pr.read_absorbance(wavelength=450) # nm
# Luminescence reading
data = await pr.read_luminescence()
# Fluorescence reading
data = await pr.read_fluorescence(
excitation_wavelength=485, # nm
emission_wavelength=535 # nm
)
```
#### Data Format
Plate reader methods return array data:
```python
import numpy as np
# Read absorbance
data = await pr.read_absorbance(wavelength=450)
# data is typically a 2D array (8x12 for 96-well plate)
print(f"Data shape: {data.shape}")
print(f"Well A1: {data[0][0]}")
print(f"Well H12: {data[7][11]}")
# Convert to DataFrame for easier handling
import pandas as pd
df = pd.DataFrame(data)
```
#### Integration with Liquid Handler
Combine plate reading with liquid handling:
```python
from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import STAR
from pylabrobot.resources import STARLetDeck
from pylabrobot.plate_reading import PlateReader
from pylabrobot.plate_reading.clario_star_backend import CLARIOstarBackend
# Initialize liquid handler
lh = LiquidHandler(backend=STAR(), deck=STARLetDeck())
await lh.setup()
# Initialize plate reader
pr = PlateReader(name="CLARIOstar", backend=CLARIOstarBackend())
await pr.setup()
# Set temperature early
await pr.set_temperature(37)
try:
# Prepare samples with liquid handler
tip_rack = TIP_CAR_480_A00(name="tips")
reagent_plate = Cos_96_DW_1mL(name="reagents")
assay_plate = Cos_96_DW_1mL(name="assay")
lh.deck.assign_child_resource(tip_rack, rails=1)
lh.deck.assign_child_resource(reagent_plate, rails=10)
lh.deck.assign_child_resource(assay_plate, rails=15)
# Transfer samples
await lh.pick_up_tips(tip_rack["A1:H1"])
await lh.transfer(
reagent_plate["A1:H12"],
assay_plate["A1:H12"],
vols=100
)
await lh.drop_tips()
# Move plate to reader (manual or robotic arm)
print("Move assay plate to plate reader")
input("Press Enter when plate is loaded...")
# Read plate
await pr.open()
# (plate loaded here)
await pr.close()
data = await pr.read_absorbance(wavelength=450)
print(f"Absorbance data: {data}")
finally:
await lh.stop()
await pr.stop()
```
#### Advanced Features
**Development Status:**
Some CLARIOstar features are under development:
- Spectral scanning
- Injector needle control
- Detailed measurement parameter configuration
- Well-specific reading patterns
Check current documentation for latest feature support.
#### Best Practices
1. **Temperature Control**: Set temperature early as heating is slow
2. **Plate Loading**: Ensure plate is properly seated before closing
3. **Measurement Selection**: Choose appropriate wavelengths for your assay
4. **Data Validation**: Check measurement quality and expected ranges
5. **Error Handling**: Handle timeout and communication errors
6. **Maintenance**: Keep optics clean per manufacturer guidelines
#### Example: Complete Plate Reading Workflow
```python
async def run_plate_reading_assay():
"""Complete workflow with sample prep and reading"""
# Initialize equipment
lh = LiquidHandler(backend=STAR(), deck=STARLetDeck())
pr = PlateReader(name="CLARIOstar", backend=CLARIOstarBackend())
await lh.setup()
await pr.setup()
# Set plate reader temperature
await pr.set_temperature(37)
try:
# Define resources
tip_rack = TIP_CAR_480_A00(name="tips")
samples = Cos_96_DW_1mL(name="samples")
assay_plate = Cos_96_DW_1mL(name="assay")
substrate = Trough_100ml(name="substrate")
lh.deck.assign_child_resource(tip_rack, rails=1)
lh.deck.assign_child_resource(substrate, rails=5)
lh.deck.assign_child_resource(samples, rails=10)
lh.deck.assign_child_resource(assay_plate, rails=15)
# Transfer samples
await lh.pick_up_tips(tip_rack["A1:H1"])
await lh.transfer(
samples["A1:H12"],
assay_plate["A1:H12"],
vols=50
)
await lh.drop_tips()
# Add substrate
await lh.pick_up_tips(tip_rack["A2:H2"])
for col in range(1, 13):
await lh.transfer(
substrate["channel_1"],
assay_plate[f"A{col}:H{col}"],
vols=50
)
await lh.drop_tips()
# Incubate (if needed)
# await asyncio.sleep(300) # 5 minutes
# Move to plate reader
print("Transfer assay plate to CLARIOstar")
input("Press Enter when ready...")
await pr.open()
input("Press Enter when plate is loaded...")
await pr.close()
# Read absorbance
data = await pr.read_absorbance(wavelength=450)
# Process results
import pandas as pd
df = pd.DataFrame(
data,
index=[f"{r}" for r in "ABCDEFGH"],
columns=[f"{c}" for c in range(1, 13)]
)
print("Absorbance Results:")
print(df)
# Save results
df.to_csv("plate_reading_results.csv")
return df
finally:
await lh.stop()
await pr.stop()
# Run assay
results = await run_plate_reading_assay()
```
## Scales
### Mettler Toledo Scales
PyLabRobot supports Mettler Toledo scales for mass measurements.
#### Setup
```python
from pylabrobot.scales import Scale
from pylabrobot.scales.mettler_toledo_backend import MettlerToledoBackend
# Create scale
scale = Scale(
name="analytical_scale",
backend=MettlerToledoBackend()
)
await scale.setup()
```
#### Operations
```python
# Get weight measurement
weight = await scale.get_weight() # Returns weight in grams
print(f"Weight: {weight} g")
# Tare (zero) the scale
await scale.tare()
# Get multiple measurements
weights = []
for i in range(5):
w = await scale.get_weight()
weights.append(w)
await asyncio.sleep(1)
average_weight = sum(weights) / len(weights)
print(f"Average weight: {average_weight} g")
```
#### Integration with Liquid Handler
```python
# Weigh samples during protocol
lh = LiquidHandler(backend=STAR(), deck=STARLetDeck())
scale = Scale(name="scale", backend=MettlerToledoBackend())
await lh.setup()
await scale.setup()
try:
# Tare scale
await scale.tare()
# Dispense liquid
await lh.pick_up_tips(tip_rack["A1"])
await lh.aspirate(reagent["A1"], vols=1000)
# (Move to scale position)
# Dispense and weigh
await lh.dispense(container, vols=1000)
weight = await scale.get_weight()
print(f"Dispensed weight: {weight} g")
# Calculate actual volume (assuming density = 1 g/mL for water)
actual_volume = weight * 1000 # Convert g to µL
print(f"Actual volume: {actual_volume} µL")
await lh.drop_tips()
finally:
await lh.stop()
await scale.stop()
```
## Other Analytical Devices
### Flow Cytometers
Some flow cytometer integrations are in development. Check current documentation for support status.
### Spectrophotometers
Additional spectrophotometer models may be supported. Check documentation for current device compatibility.
## Multi-Device Workflows
### Coordinating Multiple Devices
```python
async def multi_device_workflow():
"""Coordinate liquid handler, plate reader, and scale"""
# Initialize all devices
lh = LiquidHandler(backend=STAR(), deck=STARLetDeck())
pr = PlateReader(name="CLARIOstar", backend=CLARIOstarBackend())
scale = Scale(name="scale", backend=MettlerToledoBackend())
await lh.setup()
await pr.setup()
await scale.setup()
try:
# 1. Weigh reagent
await scale.tare()
# (place container on scale)
reagent_weight = await scale.get_weight()
# 2. Prepare samples with liquid handler
await lh.pick_up_tips(tip_rack["A1:H1"])
await lh.transfer(source["A1:H12"], dest["A1:H12"], vols=100)
await lh.drop_tips()
# 3. Read plate
await pr.open()
# (load plate)
await pr.close()
data = await pr.read_absorbance(wavelength=450)
return {
"reagent_weight": reagent_weight,
"absorbance_data": data
}
finally:
await lh.stop()
await pr.stop()
await scale.stop()
```
## Best Practices
1. **Device Initialization**: Setup all devices at start of protocol
2. **Error Handling**: Handle communication errors gracefully
3. **Cleanup**: Always call `stop()` on all devices
4. **Timing**: Account for device-specific timing (temperature equilibration, measurement time)
5. **Calibration**: Follow manufacturer calibration procedures
6. **Data Validation**: Verify measurements are within expected ranges
7. **Documentation**: Record device settings and parameters
8. **Integration Testing**: Test multi-device workflows thoroughly
9. **Concurrent Operations**: Use async to overlap operations when possible
10. **Data Storage**: Save raw data with metadata (timestamps, settings)
## Common Patterns
### Kinetic Plate Reading
```python
async def kinetic_reading(num_reads: int, interval: int):
"""Perform kinetic plate reading"""
pr = PlateReader(name="CLARIOstar", backend=CLARIOstarBackend())
await pr.setup()
try:
await pr.set_temperature(37)
await pr.open()
# (load plate)
await pr.close()
results = []
for i in range(num_reads):
data = await pr.read_absorbance(wavelength=450)
timestamp = time.time()
results.append({
"read_number": i + 1,
"timestamp": timestamp,
"data": data
})
if i < num_reads - 1:
await asyncio.sleep(interval)
return results
finally:
await pr.stop()
# Read every 30 seconds for 10 minutes
results = await kinetic_reading(num_reads=20, interval=30)
```
## Additional Resources
- Plate Reading Documentation: https://docs.pylabrobot.org/user_guide/02_analytical/
- BMG CLARIOstar Guide: https://docs.pylabrobot.org/user_guide/02_analytical/plate-reading/bmg-clariostar.html
- API Reference: https://docs.pylabrobot.org/api/pylabrobot.plate_reading.html
- Supported Equipment: https://docs.pylabrobot.org/user_guide/machines.html