{ "cells": [ { "cell_type": "markdown", "id": "e14fe3d9", "metadata": {}, "source": [ "# ResourceStack\n", "\n", "`ResourceStack` represents a collection of resources stacked together into a single\n", "resource. It can grow along the x, y or z axis. This is useful when you want to\n", "treat multiple resources as a single unit, for instance stacking lids vertically or\n", "arranging plates side by side before placing them on the deck.\n", "\n", "Because the stack is itself a `Resource`, it can be assigned to other resources or\n", "the deck like any other labware. When the stack grows along the z-axis it behaves\n", "like a traditional *stack* where items are added and removed from the top.\n", "\n", "Below we demonstrate creating stacks in different orientations and interacting with\n", "them." ] }, { "cell_type": "code", "execution_count": 1, "id": "2ebfc327", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.resources import Resource, Plate, Lid, Coordinate\n", "from pylabrobot.resources import ResourceStack" ] }, { "cell_type": "markdown", "id": "7171b4ee", "metadata": {}, "source": [ "## Creating an empty stack\n", "Pass the name and direction of growth (`\"x\"`, `\"y\"`, or `\"z\"`)." ] }, { "cell_type": "code", "execution_count": 2, "id": "1737611f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([], [], [])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stack_x = ResourceStack(\"stack_x\", \"x\")\n", "stack_y = ResourceStack(\"stack_y\", \"y\")\n", "stack_z = ResourceStack(\"stack_z\", \"z\")\n", "(stack_x.children, stack_y.children, stack_z.children)" ] }, { "cell_type": "markdown", "id": "6ae916d1", "metadata": {}, "source": [ "## Stacking resources at construction time\n", "You can also supply a list of resources which will be assigned immediately." ] }, { "cell_type": "code", "execution_count": 3, "id": "255c656a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(['A', 'B'], 20)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stack = ResourceStack(\n", " \"stack\",\n", " \"x\",\n", " [\n", " Resource(\"A\", size_x=10, size_y=10, size_z=10),\n", " Resource(\"B\", size_x=10, size_y=10, size_z=10),\n", " ],\n", ")\n", "([child.name for child in stack.children], stack.get_size_x())" ] }, { "cell_type": "markdown", "id": "41de74c4", "metadata": {}, "source": [ "The total size along the x-axis equals the sum of the children sizes." ] }, { "cell_type": "code", "execution_count": 4, "id": "c6479d0b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "20" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stack_y2 = ResourceStack(\n", " \"stack_y2\",\n", " \"y\",\n", " [\n", " Resource(\"A\", size_x=10, size_y=10, size_z=10),\n", " Resource(\"B\", size_x=10, size_y=10, size_z=10),\n", " ],\n", ")\n", "stack_y2.get_size_y()" ] }, { "cell_type": "markdown", "id": "1d1b185c", "metadata": {}, "source": [ "## Adding and removing items\n", "New items are positioned automatically at the edge returned by\n", "`get_resource_stack_edge()`. When stacking in the z direction you can only remove\n", "the current top item." ] }, { "cell_type": "code", "execution_count": 5, "id": "e35e3a75", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'L2'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lid1 = Lid(name=\"L1\", size_x=10, size_y=10, size_z=5, nesting_z_height=1)\n", "lid2 = Lid(name=\"L2\", size_x=10, size_y=10, size_z=5, nesting_z_height=1)\n", "stack_z.assign_child_resource(lid1)\n", "stack_z.assign_child_resource(lid2)\n", "stack_z.get_top_item().name" ] }, { "cell_type": "code", "execution_count": 6, "id": "7c7c11d5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'L1'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stack_z.unassign_child_resource(lid2)\n", "stack_z.get_top_item().name" ] }, { "cell_type": "markdown", "id": "b2fd5d7f", "metadata": {}, "source": [ "Attempting to remove `lid1` now would raise a `ValueError` because it is not the\n", "top item in this z-growing stack." ] }, { "cell_type": "markdown", "id": "e1e328d6", "metadata": {}, "source": [ "## Using a ResourceStack as a stacking area\n", "A common use case is stacking plates next to a reader or washer. After placing a\n", "plate on the stack you can retrieve it again using `get_top_item()`." ] }, { "cell_type": "code", "execution_count": 7, "id": "7b92cac5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plate = Plate(\"p1\", size_x=1, size_y=1, size_z=1, ordered_items={})\n", "stacking_area = ResourceStack(\"stacking_area\", \"z\")\n", "stacking_area.assign_child_resource(plate)\n", "stacking_area.get_top_item() is plate" ] }, { "cell_type": "markdown", "id": "dc9633b5", "metadata": { "lines_to_next_cell": 2 }, "source": [ "When using a :class:`~pylabrobot.liquid_handling.liquid_handler.LiquidHandler` the\n", "stack behaves just like any other resource:\n", "\n", "```python\n", "lh.move_plate(stacking_area.get_top_item(), plate_carrier[0])\n", "```\n", "\n", "This allows temporary storage of plates or lids during automated workflows." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" }, "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.15" } }, "nbformat": 4, "nbformat_minor": 5 }