Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
de9f0a7
Fix USB capture decode for malformed escape sequences
Dec 20, 2025
1e61aae
Add Tecan Infinite backend and tests
Dec 20, 2025
f50cebe
Update pylabrobot/plate_reading/tecan_infinite_backend.py
rickwierenga Dec 20, 2025
db24038
Update pylabrobot/plate_reading/tecan_infinite_backend.py
rickwierenga Dec 20, 2025
ca73508
Guard ASCII frame parsing for incomplete trailers
Dec 21, 2025
e92c6db
Refine Infinite backend decoders based on DLL plus refactoring
Dec 22, 2025
59ef4e8
Add Infinite USB lifecycle cleanup and recovery
Dec 22, 2025
da96aa2
Update Infinite backend decoder tests
Dec 23, 2025
9f49e31
remove tecanscanconfig in favor of infinite
rickwierenga Jan 21, 2026
9db0657
Add size parameter to USB.read() for precise byte reading
rickwierenga Jan 21, 2026
1e70e88
Remove PyUSBInfiniteTransport, use USB directly in Infinite backend
rickwierenga Jan 21, 2026
0c442a0
Merge branch 'main' into tecan-microplate-reader
rickwierenga Jan 21, 2026
6e0119c
Merge branch 'main' into tecan-microplate-reader
rickwierenga Jan 21, 2026
14c69fa
Merge branch 'main' into tecan-microplate-reader
rickwierenga Jan 21, 2026
bbc0bd9
Refactor Tecan Infinite backend to use io/binary Reader
rickwierenga Jan 21, 2026
0af381d
move into tecan package
rickwierenga Jan 21, 2026
dc783d7
Merge main into tecan-microplate-reader
rickwierenga Jan 21, 2026
0219a2c
Simplify _end_run to use _active_step_loss_commands directly
rickwierenga Jan 21, 2026
0de19f2
Simplify command sending in configure and cleanup methods
rickwierenga Jan 21, 2026
cb6336e
Simplify method names by removing redundant "ascii" qualifier
rickwierenga Jan 21, 2026
4448f0a
Add command verification tests for Tecan Infinite backend
rickwierenga Jan 24, 2026
d71ff9f
Merge branch 'main' into tecan-microplate-reader
rickwierenga Jan 24, 2026
9bff32c
Extract common scan loop into _run_scan helper
rickwierenga Jan 24, 2026
1e89fce
Remove duplicate well computation in _run_scan
rickwierenga Jan 24, 2026
31861e3
remove unused state from configuration
rickwierenga Jan 24, 2026
98c6490
Extract common CLEAR commands into _clear_mode_settings helper
rickwierenga Jan 24, 2026
793a7c8
Rename Prepare to Calibration in infinite backend
rickwierenga Jan 24, 2026
4251a5e
Fix type checking errors in decoder _handle_bin methods
rickwierenga Jan 24, 2026
e487d0b
Rename marker to payload_len in infinite backend
rickwierenga Jan 24, 2026
3dceb24
Remove packet logging functionality from infinite backend
rickwierenga Jan 24, 2026
073e45e
type
rickwierenga Jan 24, 2026
f407ae2
Fix Python 3.9 compatibility for asyncio.Lock in infinite backend
rickwierenga Jan 24, 2026
6c970ad
Fix integration time unit conversion
Jan 30, 2026
9ea153a
Use focal_height parameter for Z position in fluorescence and lumines…
rickwierenga Jan 31, 2026
738ca07
Remove _device_initialized flag and simplify initialization
rickwierenga Jan 31, 2026
0c9ec37
Merge branch 'main' into tecan-microplate-reader
rickwierenga Jan 31, 2026
9b45fa6
Remove _device_initialized references from tests
rickwierenga Jan 31, 2026
156bc63
Add Tecan Infinite 200 PRO to machine overview
rickwierenga Jan 31, 2026
a4fb8ef
Add Tecan Infinite 200 PRO tutorial documentation
rickwierenga Jan 31, 2026
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
18 changes: 2 additions & 16 deletions docs/user_guide/02_analytical/plate-reading/plate-reading.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,7 @@
"cell_type": "markdown",
"id": "39d0c1a5",
"metadata": {},
"source": [
"# Plate reading\n",
"\n",
"PyLabRobot supports the following plate readers:\n",
"\n",
"```{toctree}\n",
":maxdepth: 1\n",
"\n",
"bmg-clariostar\n",
"cytation\n",
"synergyh1\n",
"```\n",
"\n",
"This example uses the `PlateReaderChatterboxBackend`. When using a real machine, use the corresponding backend."
]
"source": "# Plate reading\n\nPyLabRobot supports the following plate readers:\n\n```{toctree}\n:maxdepth: 1\n\nbmg-clariostar\ncytation\nsynergyh1\ntecan-infinite\n```\n\nThis example uses the `PlateReaderChatterboxBackend`. When using a real machine, use the corresponding backend."
},
{
"cell_type": "code",
Expand Down Expand Up @@ -432,4 +418,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
186 changes: 186 additions & 0 deletions docs/user_guide/02_analytical/plate-reading/tecan-infinite.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tecan Infinite 200 PRO\n",
"\n",
"The Tecan Infinite 200 PRO is a multimode microplate reader that supports absorbance, fluorescence, and luminescence measurements. This backend targets the Infinite \"M\" series (e.g., Infinite 200 PRO M Plex)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pylabrobot.plate_reading import PlateReader\n",
"from pylabrobot.plate_reading.tecan import TecanInfinite200ProBackend"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pr = PlateReader(name=\"PR\", size_x=0, size_y=0, size_z=0, backend=TecanInfinite200ProBackend())\n",
"await pr.setup()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"await pr.open()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before closing, assign a plate to the plate reader. This determines the well positions for measurements."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pylabrobot.resources import Cor_96_wellplate_360ul_Fb\n",
"plate = Cor_96_wellplate_360ul_Fb(name=\"plate\")\n",
"pr.assign_child_resource(plate)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"await pr.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Absorbance\n",
"\n",
"Read absorbance at a specified wavelength (230-1000 nm)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"data = await pr.read_absorbance(wavelength=450)\n",
"plt.imshow(data)\n",
"plt.colorbar(label=\"OD\")\n",
"plt.title(\"Absorbance at 450 nm\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fluorescence\n",
"\n",
"Read fluorescence with specified excitation and emission wavelengths (230-850 nm) and focal height."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data = await pr.read_fluorescence(\n",
" excitation_wavelength=485,\n",
" emission_wavelength=528,\n",
" focal_height=7.5\n",
")\n",
"plt.imshow(data)\n",
"plt.colorbar(label=\"RFU\")\n",
"plt.title(\"Fluorescence (Ex: 485 nm, Em: 528 nm)\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Luminescence\n",
"\n",
"Read luminescence with a specified focal height."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data = await pr.read_luminescence(focal_height=4.5)\n",
"plt.imshow(data)\n",
"plt.colorbar(label=\"RLU\")\n",
"plt.title(\"Luminescence\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Reading specific wells\n",
"\n",
"You can specify a subset of wells to read instead of the entire plate."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"wells = plate.get_items([\"A1\", \"A2\", \"B1\", \"B2\"])\n",
"data = await pr.read_absorbance(wavelength=450, wells=wells)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cleanup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"await pr.stop()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
1 change: 1 addition & 0 deletions docs/user_guide/machines.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ tr > td:nth-child(5) { width: 15%; }
| Byonoy | Luminescence 96 Automate | <span class="badge badge-luminescence">luminescence</span> | WIP | [OEM](https://byonoy.com/luminescence-96-automate/) |
| Molecular Devices | SpectraMax M5e | <span class="badge badge-absorbance">absorbance</span><span class="badge badge-fluorescence">fluorescence</span> <span class="badge badge-time-resolved-fluo">time-resolved fluorescence</span><span class="badge badge-fluo-polarization">fluorescence polarization</span> | Full | [OEM](https://www.moleculardevices.com/products/microplate-readers/multi-mode-readers/spectramax-m-series-readers) |
| Molecular Devices | SpectraMax 384plus | <span class="badge badge-absorbance">absorbance</span> | Full | [OEM](https://www.moleculardevices.com/products/microplate-readers/absorbance-readers/spectramax-abs-plate-readers) |
| Tecan | Infinite 200 PRO | <span class="badge badge-absorbance">absorbance</span><span class="badge badge-fluorescence">fluorescence</span><span class="badge badge-luminescence">luminescence</span> | Mostly | [PLR](https://docs.pylabrobot.org/user_guide/02_analytical/plate-reading/tecan-infinite.html) / [OEM](https://lifesciences.tecan.com/infinite-200-pro) |


### Flow Cytometers
Expand Down
1 change: 1 addition & 0 deletions pylabrobot/plate_reading/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@
ImagingResult,
Objective,
)
from .tecan import InfiniteScanConfig, TecanInfinite200ProBackend
1 change: 1 addition & 0 deletions pylabrobot/plate_reading/tecan/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .infinite_backend import InfiniteScanConfig, TecanInfinite200ProBackend
Loading