diff --git a/docs/resources/index.md b/docs/resources/index.md index 86aa4006dbc..58402cd0e45 100644 --- a/docs/resources/index.md +++ b/docs/resources/index.md @@ -98,7 +98,7 @@ PLR's `Resource` subclasses in the inheritance tree are: ├── TipSpot - ├── Lid + ├── Lid ├── PetriDishHolder ├── PlateAdapter @@ -133,6 +133,7 @@ deck/deck itemized-resource/itemized-resource itemized-resource/tube-rack/tube-rack resource-holder/resource-holder +lid/lid plate-adapter/plate-adapter petri-dish-holder/petri-dish-holder resource-stack/resource-stack diff --git a/docs/resources/itemized-resource/plate/plate.rst b/docs/resources/itemized-resource/plate/plate.rst index 63ab1ba2d4f..bbb83aac5ff 100644 --- a/docs/resources/itemized-resource/plate/plate.rst +++ b/docs/resources/itemized-resource/plate/plate.rst @@ -39,7 +39,7 @@ This standard is similar to the `Opentrons API labware naming standard `. ---- diff --git a/docs/resources/lid/lid.ipynb b/docs/resources/lid/lid.ipynb new file mode 100644 index 00000000000..9e11eeb5e59 --- /dev/null +++ b/docs/resources/lid/lid.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "lid-intro", + "metadata": {}, + "source": [ + "# Lid\n", + "\n", + "A {class}`~pylabrobot.resources.Lid` is a removable cover for a plate, a tip rack or a container.\n", + "It is a resource of its own: a lid on a plate is one of the plate's children, next to its wells,\n", + "and it can be taken off and put back." + ] + }, + { + "cell_type": "markdown", + "id": "creating-a-lid", + "metadata": {}, + "source": [ + "## Creating a lid\n", + "\n", + "Besides a name and its outer dimensions, a lid has a `nesting_z_height`: the overlap, in mm,\n", + "between the lid and the resource it covers, in the z direction. `size_z` is the lid's full height.\n", + "Both can be measured with a caliper:\n", + "\n", + "![Measuring size_z and nesting_z_height](../img/plate/lid_nesting_z_height.jpeg)\n", + "\n", + "The lid below has the dimensions of `cor_96_wellplate_360uL_Fb_lid` in the resource library, the\n", + "lid of a Corning 96-well plate:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "create-example", + "metadata": {}, + "outputs": [], + "source": [ + "from pylabrobot.resources import Lid\n", + "\n", + "lid = Lid(\n", + " name=\"plate_lid\",\n", + " size_x=127.76,\n", + " size_y=85.48,\n", + " size_z=8.9,\n", + " nesting_z_height=7.6,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "putting-a-lid-on", + "metadata": {}, + "source": [ + "## Putting a lid on\n", + "\n", + "Set the plate's `lid`, or assign the lid to the plate with `assign_child_resource`. Unless a\n", + "location is given, the lid is centred on the plate's top face and lowered by its\n", + "`nesting_z_height`. The lid's location, like any child's, is relative to the plate:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "put-on-example", + "metadata": {}, + "outputs": [], + "source": [ + "from pylabrobot.resources import Coordinate, cor_96_wellplate_360uL_Fb\n", + "\n", + "plate = cor_96_wellplate_360uL_Fb(name=\"plate\") # 14.2 mm tall\n", + "plate.lid = lid # the same as plate.assign_child_resource(lid)\n", + "\n", + "assert plate.lid is lid\n", + "assert lid.location == Coordinate(0, 0, 14.2 - 7.6)" + ] + }, + { + "cell_type": "markdown", + "id": "lid-at-creation", + "metadata": {}, + "source": [ + "`Plate(..., lid=lid)` puts a lid on when the plate is created. Some library plates\n", + "do this when called with `with_lid=True`: `cor_96_wellplate_360uL_Fb(name=\"plate\",\n", + "with_lid=True)` creates the same plate with the library's `cor_96_wellplate_360uL_Fb_lid` on,\n", + "named `plate_lid`.\n", + "\n", + "The lid is one of the plate's `children`, next to its wells. The plate's item methods, such as\n", + "`get_all_items()`, return only the wells." + ] + }, + { + "cell_type": "markdown", + "id": "taking-a-lid-off", + "metadata": {}, + "source": [ + "## Taking a lid off\n", + "\n", + "Unassign the lid, or set the plate's `lid` to `None`. The lid then has no parent and no location:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "take-off-example", + "metadata": {}, + "outputs": [], + "source": [ + "lid.unassign() # the same as plate.lid = None\n", + "\n", + "assert not plate.has_lid()\n", + "assert lid.parent is None and lid.location is None" + ] + }, + { + "cell_type": "markdown", + "id": "model-only", + "metadata": {}, + "source": [ + "Putting a lid on and taking it off change only the resource model; they do not move a physical\n", + "lid." + ] + }, + { + "cell_type": "markdown", + "id": "resources-that-take-a-lid", + "metadata": {}, + "source": [ + "## Resources that take a lid\n", + "\n", + "A resource takes a lid through the `Liddable` mixin, which provides `lid`, `has_lid()` and\n", + "`get_lid_location()`, the location used above. {class}`~pylabrobot.resources.Plate`,\n", + "{class}`~pylabrobot.resources.TipRack` and {class}`~pylabrobot.resources.Container` (troughs,\n", + "tubes, petri dishes and wells) are liddable; a lid is not.\n", + "\n", + "A liddable resource holds one lid at a time: putting on a second raises `ValueError`. So does a lid\n", + "more than 1 mm smaller than the resource in x or y, which could not cover it. A larger lid is\n", + "centred, so it overhangs evenly:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "trough-example", + "metadata": {}, + "outputs": [], + "source": [ + "from pylabrobot.resources import hamilton_1_trough_200mL_Vb\n", + "\n", + "trough = hamilton_1_trough_200mL_Vb(name=\"trough\") # 37 x 118 x 95 mm\n", + "trough_lid = Lid(\n", + " name=\"trough_lid\",\n", + " size_x=39,\n", + " size_y=120,\n", + " size_z=10,\n", + " nesting_z_height=4,\n", + ")\n", + "trough.lid = trough_lid\n", + "\n", + "assert trough_lid.location == Coordinate(-1, -1, 95 - 4)" + ] + }, + { + "cell_type": "markdown", + "id": "api-reference", + "metadata": {}, + "source": [ + "See {class}`~pylabrobot.resources.Lid` for the API reference." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}