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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Added

- Agilent BenchCel 4R storage backend (`pylabrobot.storage.agilent.BenchCel4RBackend`) speaking the reverse-engineered binary TCP/7612 protocol, plus a `BenchCel4R(...)` factory, calculation-based BenchCel labware/rack sizing helpers, a `set_labware(...)` command that pushes labware geometry to the device via the decoded `0x7d`/`0x9f` settings protocol, an in-process mock server, and a user guide. Opening the stacker clamps (which can drop a plate stack) is exposed as `dangerously_open_stacker_grippers`.
- HighRes Biosolutions MicroSpin centrifuge backend (`pylabrobot.centrifuge.highres.MicroSpinBackend`) speaking the device's ASCII command/response protocol over TCP/1000, plus a `MicroSpin(...)` factory.
- In-process `MicroSpinMockServer` (`pylabrobot.centrifuge.highres.mock_server`) that faithfully emulates the MicroSpin's wire protocol -- including the firmware's "`status` blocks until the spindle has stopped" semantics and the low-G spin-down-detection hang -- usable as a Python async context manager or runnable as a script (`python -m pylabrobot.centrifuge.highres.mock_server`) for `nc`/`telnet` debugging.
- `MicroSpinBackend.reset()` recovery helper that issues `abort` -> `clearbuttonabort` -> `status`, using the last as the gate that genuinely confirms the rotor has stopped.
Expand Down
1 change: 1 addition & 0 deletions docs/api/pylabrobot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Subpackages
pylabrobot.only_fans
pylabrobot.resources
pylabrobot.scales
pylabrobot.storage
pylabrobot.io.sila
pylabrobot.shaking
pylabrobot.temperature_controlling
Expand Down
70 changes: 70 additions & 0 deletions docs/api/pylabrobot.storage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
.. currentmodule:: pylabrobot.storage

pylabrobot.storage package
==========================

This package contains APIs for automated storage devices and incubators.

.. autosummary::
:toctree: _autosummary
:nosignatures:
:recursive:

incubator.Incubator
agilent.benchcel.BenchCel4R


Backends
--------

.. autosummary::
:toctree: _autosummary
:nosignatures:
:recursive:

backend.IncubatorBackend
agilent.benchcel_backend.BenchCel4RBackend
cytomat.cytomat.CytomatBackend
liconic.liconic_backend.ExperimentalLiconicBackend


Agilent BenchCel support classes
--------------------------------

.. autosummary::
:toctree: _autosummary
:nosignatures:
:recursive:

agilent.benchcel_backend.Frame
agilent.benchcel_backend.SensorStatus
agilent.benchcel_backend.ArmStatus
agilent.benchcel_backend.GeneralStatus
agilent.benchcel_backend.Teachpoint
agilent.benchcel_backend.AxisBoundsResponse
agilent.benchcel_backend.CurrentPositionResponse
agilent.benchcel_labware.BenchCelLabwareSettings
agilent.benchcel_labware.PlateNotchSettings
agilent.benchcel_labware.apply_benchcel_labware_settings
agilent.benchcel_labware.calculate_benchcel_labware_settings
agilent.benchcel_labware.calculate_robot_gripper_offset
agilent.benchcel_labware.calculate_sensor_offset
agilent.benchcel_labware.calculate_stacker_gripper_offset
agilent.benchcel_labware.calculate_stacking_thickness
agilent.benchcel_mock_server.BenchCelMockServer
agilent.racks.benchcel_stacker_rack
agilent.racks.benchcel_4r_racks
agilent.racks.benchcel_4r_racks_for_labware


Errors
------

.. autosummary::
:toctree: _autosummary
:nosignatures:
:recursive:

agilent.benchcel_backend.BenchCelDeviceError
agilent.benchcel_backend.BenchCelProtocolError
agilent.benchcel_backend.BenchCelTimeoutError
4 changes: 4 additions & 0 deletions docs/contributor_guide/contributing-new-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def AGenBio_96_wellplate_Ub_2200ul(name: str, lid: Optional[Lid] = None) -> Plat
size_x=127.76, # from spec
size_y=85.48, # from spec
size_z=42.5, # from spec
# Optional: the vertical pitch one plate adds to a stack of identical plates
# (size_z minus how far two identical plates nest). Only needed by plate
# stackers (e.g. the Agilent BenchCel); leave unset (None) otherwise.
stacking_z_height=39.0, # measured
...
)
````
Expand Down
18 changes: 18 additions & 0 deletions docs/resources/itemized-resource/plate/plate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,21 @@ The ``nesting_z_height`` is the overlap between the lid and the plate when the l

.. image:: /resources/img/plate/lid_nesting_z_height.jpeg
:alt: nesting_z_height measurement

----

``stacking_z_height``
---------------------
:class:`~pylabrobot.resources.plate.Plate` accepts an optional ``stacking_z_height`` argument: the vertical pitch (in mm) that one plate adds to a stack when an identical plate is placed directly on top of it. Equivalently, it is ``size_z`` minus the amount two identical plates nest into one another.

It defaults to ``None`` (unknown) and is only required by devices that physically stack plates, such as the Agilent BenchCel microplate handler. It mirrors the ``stacking_z_height`` of a nested tip rack (:class:`~pylabrobot.resources.tip_rack.NestedTipRack`).

To measure it, stack two identical plates and measure the total height with a caliper; then::

stacking_z_height = height_of_two_stacked_plates - size_z

More generally, a stack of ``N`` identical plates is ``size_z + (N - 1) * stacking_z_height`` tall.

When set, :class:`~pylabrobot.resources.resource_stack.ResourceStack` uses this value so that bare plates stacked in the z direction nest into one another (a plate placed on another bare plate sinks in by ``size_z - stacking_z_height``). Plates without a ``stacking_z_height``, and plates wearing a lid, do not nest.

Because ``stacking_z_height`` is a physical dimension, two plates that differ in it are treated as different labware and do not compare equal.
31 changes: 31 additions & 0 deletions docs/resources/resource-stack/resource-stack.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,37 @@
"stacking_area.get_top_item() is plate"
]
},
{
"cell_type": "markdown",
"id": "a1b2c3d4",
"metadata": {},
"source": [
"### Nesting plates by `stacking_z_height`\n",
"\n",
"Bare plates that define a `stacking_z_height` nest into one another when stacked in the\n",
"z direction: a plate placed on another bare plate sinks in by `size_z - stacking_z_height`,\n",
"so a stack of `N` identical plates is `size_z + (N - 1) * stacking_z_height` tall instead of\n",
"`N * size_z`. Plates without a `stacking_z_height`, and plates wearing a lid, do not nest.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a1b2c3d5",
"metadata": {},
"outputs": [],
"source": [
"nesting_stack = ResourceStack(\"nesting_stack\", \"z\")\n",
"nesting_stack.location = Coordinate.zero()\n",
"for i in range(3):\n",
" nesting_stack.assign_child_resource(\n",
" Plate(f\"plate_{i}\", size_x=127, size_y=86, size_z=14, ordered_items={}, stacking_z_height=4)\n",
" )\n",
"\n",
"# 14 + (3 - 1) * 4 = 22, not 3 * 14 = 42\n",
"nesting_stack.get_size_z()"
]
},
{
"cell_type": "markdown",
"id": "dc9633b5",
Expand Down
Loading
Loading