Opentrons App & API 2.5.0 Release

The Opentrons API has undergone a significant refactor that changes the way it works underneath the hood. These changes do not impact what the API does but rather how it does them. This document will walk you through the changes that have taken place and show you how you can leverage these updates for productivity and better integration with external tools when running protocols outside of the Opentrons App (e.g. in a Jupyter environment).

Execution Model Updates

Previously the Opentrons API would take a series of robot commands (aspirate, dispense, etc) and enqueue them for execution at a later time. API commands were run only when the user called the run method on the robot instance. I.e. “robot.run()”. The new model moving forward allows the API to execute user commands at runtime (when the code in a Jupyter cell is executed).

This new model allows users to control external devices and/or run other python code alongside the Opentrons robot. Let’s take a look at what this means in code.

Previously if you had the following protocol (imports truncated for brevity).

p200.aspirate(100, plate[‘A1’])  
camera.take_picture()  
p200.dispense(100, plate[‘A1’])

robot.run()  

This protocol would result in the following actions with the previous execution sequence,

  1. The robot will enqueue a command to aspirate
  2. The camera will execute taking picture
  3. The robot will enqueue a command to dispense
  4. The robot will run the previously enqueued aspirate command
  5. The robot will run the previously enqueued dispense command

The problem with this execution order is the camera picture is taken before the aspirate command. From reading the code one would think the taking of the picture would happen after the aspirate command and before the dispense command.

Deprecated Commands

Since commands are no longer enqueued and then executed the following methods/arguments will no longer be relevant:

  • robot.run()
  • robot.simulate()
  • Any command with the argument enqueue=True|False. E.g. robot.home(enqueue=True)
  • robot.send_to_app()

Here are scenarios in which these commands were used and explanations on the new way of doing things.

Running the Robot

Before: You could run your protocol on the robot by calling robot.run()

Now: Just execute your Jupyter cell or python script with your protocol code while connected to a robot.

Protocol simulation

Before: You could call robot.simulate() to run your protocol in simulation mode.

Now: Connect the robot to null connection: robot.connect() and all commands in your protocol will run against a virtual robot within the API.

Enqueued commands

Before: You could instruct certain commands in your protocol to run immediately by specifying enqueue=True e.g. robot.home(enqueue=True)

Now: You can just call robot.home() and the API will dispatch commands to the device you are connected to. If you are connected to an actual robot you would call robot.connect('/dev/ttyACM0') or robot.connect('COM3'). If you wanted to connect to a virtual robot for simulation you don't specify a port as an argument to the connection method: robot.connect() -- this will connect to a virtual robot and simulate your protocol commands.

Sending protocol from Jupyter to the app

Before: You could run robot.send_to_app() at the end of your python protocol and it would serialize your enqueued robot commands and send them to the app (if the app was running).

Now: We recommend manually uploading your protocol file to the app. We are developing better ways to allow you to write protocols and calibrate with the app.

Next Steps

To try out the new API by installing it on your computer with pip. Just go to your Python environment and run: pip install opentrons==2.5.0.