{ "cells": [ { "cell_type": "markdown", "id": "intro", "metadata": {}, "source": [ "# BTX Gemini X2\n", "\n", "The BTX Gemini X2 is a twin-waveform electroporator. PyLabRobot controls it through a USB serial connection: protocol and log transfer use the Gemini file-transfer interface, while run-screen actions use GhostTouch on the instrument touchscreen.\n", "\n", "See the [installation instructions](installation.md) before connecting the instrument.\n", "\n", "Protocol and run-result models are provided by the Gemini X2 package." ] }, { "cell_type": "markdown", "id": "device-card", "metadata": {}, "source": [ "```{device-card} btx-gemini-x2\n", "```" ] }, { "cell_type": "markdown", "id": "setup-md", "metadata": {}, "source": [ "## Setup\n", "\n", "Identify the serial port on your control computer and create the device. On macOS this is often `/dev/cu.usbmodem...`; on Windows it is usually a `COM` port." ] }, { "cell_type": "code", "execution_count": null, "id": "setup-code", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.thermo_fisher.btx.gemini.X2 import BTXGeminiX2\n", "\n", "gemini = BTXGeminiX2(port=\"/dev/cu.usbmodemXXXX\")\n", "await gemini.setup()" ] }, { "cell_type": "markdown", "id": "info-md", "metadata": {}, "source": [ "## Device information\n", "\n", "The Gemini X2 exposes device identity, the temporary protocol prefix, and plate-handler support." ] }, { "cell_type": "code", "execution_count": null, "id": "info-code", "metadata": {}, "outputs": [], "source": [ "info = await gemini.request_device_info()\n", "print(info[\"model\"], info[\"version\"], info[\"serial_number\"])" ] }, { "cell_type": "markdown", "id": "protocol-md", "metadata": {}, "source": [ "## Define a protocol\n", "\n", "Square-wave protocols use `duration_us`; exponential-decay protocols use `resistance_ohms` and `capacitance_uf`." ] }, { "cell_type": "code", "execution_count": null, "id": "protocol-code", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.thermo_fisher.btx.gemini.X2 import ElectroporationProtocol\n", "\n", "protocol = ElectroporationProtocol(\n", " protocol_type=\"square\",\n", " pulse_amplitude_volts=250,\n", " gap_mm=2.0,\n", " pulse_count=1,\n", " pulse_interval_seconds=0.0,\n", " duration_us=1000,\n", ")" ] }, { "cell_type": "markdown", "id": "prepare-md", "metadata": {}, "source": [ "## Prepare a temporary run\n", "\n", "`prepare_temporary_protocol` writes a temporary `!PLR_...` user protocol, opens it on the Gemini touchscreen, sets plate-handler columns when requested, and leaves the device on the run screen.\n", "\n", "When using the HT-200 plate handler, first record its configured pulse count and column adjustment. `plate_columns` also requires an explicit `plate_handler_reset_state`. Use `reset_confirmed` only after manually returning the handler to column 1; use `continue_current_position` only when intentionally continuing from the current handler position." ] }, { "cell_type": "code", "execution_count": null, "id": "prepare-code", "metadata": {}, "outputs": [], "source": [ "gemini.plate_handler.configure_manual_state(pulse_count=1, column_adjust=0)\n", "\n", "prepared = await gemini.prepare_temporary_protocol(\n", " protocol=protocol,\n", " plate_columns=3,\n", " plate_handler_reset_state=\"reset_confirmed\",\n", ")\n", "prepared.protocol_name" ] }, { "cell_type": "markdown", "id": "serialize-md", "metadata": {}, "source": [ "The prepared run can be serialized and passed to a later process. The serialized payload includes the temporary protocol name and baseline log listing used to match the new BTXDATA log after GO." ] }, { "cell_type": "code", "execution_count": null, "id": "serialize-code", "metadata": {}, "outputs": [], "source": [ "prepared_payload = prepared.as_dict()\n", "prepared_payload[\"protocol_name\"]" ] }, { "cell_type": "markdown", "id": "start-md", "metadata": {}, "source": [ "## Start the prepared run\n", "\n", "The next cell presses GO on the prepared run screen and delivers the configured pulse. Confirm that the plate, electrodes, samples, safety cover, and plate-handler state are correct before running it." ] }, { "cell_type": "code", "execution_count": null, "id": "start-code", "metadata": {}, "outputs": [], "source": [ "result = await gemini.start_prepared_run(\n", " prepared_run=prepared,\n", " home_after=True,\n", ")\n", "result.log_capture.summary" ] }, { "cell_type": "markdown", "id": "cancel-md", "metadata": {}, "source": [ "## Cancel before pulse delivery\n", "\n", "If a run has been prepared but should not be started, cancel it. This returns the Gemini to a safe screen and deletes the temporary protocol." ] }, { "cell_type": "code", "execution_count": null, "id": "cancel-code", "metadata": {}, "outputs": [], "source": [ "# cancelled = await gemini.cancel_prepared_run(prepared)\n", "# cancelled.cleanup.deleted" ] }, { "cell_type": "markdown", "id": "teardown-md", "metadata": {}, "source": [ "## Teardown" ] }, { "cell_type": "code", "execution_count": null, "id": "teardown-code", "metadata": {}, "outputs": [], "source": [ "await gemini.stop()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.12.0" } }, "nbformat": 4, "nbformat_minor": 5 }