{ "cells": [ { "cell_type": "markdown", "id": "b63b4656", "metadata": {}, "source": [ "# Liconic STX Series\n", "\n", "The Liconic STX line of automated incubators come in a variety of sizes including STX 1000, STX 500, STX 280, STX 220, STX 110, STX 44. Which corresponds to the number of plates each size can store using the standard 22 plate capacity cassettes/cartridges (plate height 17mm, 505mm total height.) There are other cassette size for plates height ranging from 5 to 104mm in height (higher plates = less number of plates storage capacity.)\n", "\n", "The Liconic STX line comes in a variety of climate control options including Ultra High Temp. (HTT), Incubator (IC), Dry Storage (DC2), Humid Cooler (HC), Humid Wide Range (HR), Dry Wide Range (DR2), Humidity Controlled (AR), Deep Freezer (DF) and Ultra Deep Freezer (UDF). Each have different ranges of temperatures and humidity control ability.\n", "\n", "Other accessories that can be included with the STX and can be utilized with this driver include N2 gassing, CO2 gassing, a Turn Station (rotation of plates 90 degrees on the transfer station), internal barcode scanners, a swap station (two transfer plate positions that can be rotated 180 degrees) and internal shaking. \n", "\n", "This tutorial shows how to\n", " - Connect the Liconic incubator\n", " - Configure racks\n", " - Move plates in and out\n", " - Set and monitor temperature and humidity values" ] }, { "cell_type": "code", "execution_count": null, "id": "fcd75e15", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.barcode_scanners import BarcodeScanner, KeyenceBarcodeScannerBackend\n", "from pylabrobot.resources.coordinate import Coordinate\n", "from pylabrobot.storage import ExperimentalLiconicBackend\n", "from pylabrobot.storage.incubator import Incubator\n", "from pylabrobot.storage.liconic.racks import liconic_rack_17mm_22, liconic_rack_44mm_10\n", "\n", "\n", "barcode_scanner_backend = KeyenceBarcodeScannerBackend(port=\"COM4\")\n", "barcode_scanner = BarcodeScanner(backend=barcode_scanner_backend)\n", "\n", "liconic_backend = ExperimentalLiconicBackend(port=\"COM3\", model=\"STX220_HC\", barcode_scanner=barcode_scanner)\n", "\n", "rack = [\n", " liconic_rack_44mm_10(\"cassette_0\"),\n", " liconic_rack_44mm_10(\"cassette_1\"),\n", " liconic_rack_44mm_10(\"cassette_2\"),\n", " liconic_rack_17mm_22(\"cassette_3\"),\n", " liconic_rack_17mm_22(\"cassette_4\"),\n", " liconic_rack_17mm_22(\"cassette_5\"),\n", " liconic_rack_17mm_22(\"cassette_6\"),\n", " liconic_rack_17mm_22(\"cassette_7\"),\n", " liconic_rack_17mm_22(\"cassette_8\"),\n", " liconic_rack_17mm_22(\"cassette_9\")\n", "]\n", "\n", "incubator = Incubator(\n", " backend=liconic_backend,\n", " name=\"My Incubator\",\n", " size_x=100, size_y=100, size_z=100, # stubs for now...\n", " racks=rack,\n", " loading_tray_location=Coordinate(x=0, y=0, z=0),\n", ")\n", "\n", "await incubator.setup()" ] }, { "cell_type": "markdown", "id": "19b3a6cc", "metadata": { "vscode": { "languageId": "plaintext" } }, "source": [ "## Setup\n", "\n", "To setup the incubator and start sending commands first the backed needs to be declared. For the Liconic the LiconcBackend class is used with the COM port used for connection (in this case COM3) and the model needs to specified (in this case the STX 220 Humid Cooler, STX220_HC). If an internal barcode is installed the barcode_installed parameter is set to True and its COM port is also specified. These two parameters are optional so can be omitted for Liconics without an internal barcode scanner. \n", "\n", "Given a STX 220 (220 plate position / 22 plates per rack = 10 racks) can hold 10 racks the list of racks is built and includes mixing and matching different plate height racks. The differences in racks are handled prior to plate retrieval and storage. \n", "\n", "Once the these are built the base Incubator class is created and the connection to the incubator is initialized using:" ] }, { "cell_type": "code", "execution_count": null, "id": "9d7a4f49", "metadata": {}, "outputs": [], "source": [ "await incubator.setup()" ] }, { "cell_type": "markdown", "id": "52f79811", "metadata": {}, "source": [ "## Usage\n", "\n", "To store a plate first a plate resource is initialized and then assigned to the loading tray. The method take_in_plate is then called on the incubator object." ] }, { "cell_type": "code", "execution_count": null, "id": "d26e039d", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.resources import Azenta4titudeFrameStar_96_wellplate_200ul_Vb\n", "\n", "new_plate = Azenta4titudeFrameStar_96_wellplate_200ul_Vb(name=\"TEST\")\n", "incubator.loading_tray.assign_child_resource(new_plate)\n", "await incubator.take_in_plate(\"smallest\") # choose the smallest free site\n", "\n", "# other options:\n", "# await incubator.take_in_plate(\"random\") # random free site\n", "# await incubator.take_in_plate(rack[3]) # store at rack position 3" ] }, { "cell_type": "markdown", "id": "85dcddb7", "metadata": {}, "source": [ "To retrieve a plate the plate name can used" ] }, { "cell_type": "code", "execution_count": null, "id": "00308838", "metadata": {}, "outputs": [], "source": [ "await incubator.fetch_plate_to_loading_tray(plate_name=\"TEST\")\n", "retrieved = incubator.loading_tray.resource" ] }, { "cell_type": "markdown", "id": "0045e703", "metadata": {}, "source": [ "You can also print a barcode from this call (if barcode is installed per the backend insatiation). Returning of the barcode as a return object still needs to be implemented. Currently the barcode is just printed to the terminal.\n", "\n", "Barcode can returned by setting the read_barcode to True for \n", "- take_in_plate\n", "- fetch_plate_to_loading_tray\n", "- move_position_to_position" ] }, { "cell_type": "code", "execution_count": null, "id": "c8730560", "metadata": {}, "outputs": [], "source": [ "position = rack[9][0] # rack number 9 position 1\n", "\n", "await incubator.fetch_plate_to_loading_tray(plate_name=\"TEST\", read_barcode=True)\n", "\n", "await incubator.take_in_plate(position, read_barcode=True)\n" ] }, { "cell_type": "markdown", "id": "d137d333", "metadata": {}, "source": [ "move plate from one internal position to another internal position" ] }, { "cell_type": "code", "execution_count": null, "id": "1aa68983", "metadata": {}, "outputs": [], "source": [ "await liconic_backend.move_position_to_position(plate=new_plate, dest_site=position, read_barcode=True)\n", "# will set new_plate.barcode to the barcode read from the plate at position and move it to position." ] }, { "cell_type": "markdown", "id": "14efdf69", "metadata": {}, "source": [ "The humdity, temperature, N2 gas and CO2 gas levels can all be controlled and queried. For temperature for example:\n", "\n", "- To get the current temperature" ] }, { "cell_type": "code", "execution_count": null, "id": "73e38f2a", "metadata": {}, "outputs": [], "source": [ "temperature = await liconic_backend.get_temperature() # returns temperature as float in Celsius to the 10th place\n", "print(str(temperature))" ] }, { "cell_type": "markdown", "id": "c7383277", "metadata": {}, "source": [ "- To set the temperature of the Liconic" ] }, { "cell_type": "code", "execution_count": null, "id": "2c51c385", "metadata": {}, "outputs": [], "source": [ "await incubator.set_temperature(8.0) # set the temperature to 8 degrees Celsius" ] }, { "cell_type": "markdown", "id": "4f07f349", "metadata": {}, "source": [ "- You can also retrieve the set value (the value sent for set_temperature) using:" ] }, { "cell_type": "code", "execution_count": null, "id": "288dea91", "metadata": {}, "outputs": [], "source": [ "set_temperature = await liconic_backend.get_target_temperature() # will return a float for the set temperature in degrees Celsius" ] }, { "cell_type": "markdown", "id": "3a1d9ef3", "metadata": {}, "source": [ "This pattern is the same for CO2, N2 and Humidity control of the Liconic. " ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }