Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.


Laboratory Open Procotol Language (LabOP) is a representation designed to simplify the exchange of protocols between laboratories. This project includes both an ontology describing LabOP and a python library to manipulate LabOP documents, which are stored as RDF. The LabOP specification is in the LabOP-specification repository.


The LabOP package is available by PyPI:

pip3 install labop

The LabOP repo also includes git submodules containing the optional utility labop-check for checking consistency of protocol representations and a demo version of the container-ontology which provides standardized descriptions for laboratory containers. These are currently not available as packages. If you wish to use these you will have to clone the LabOP repo and install each of these separately:

git clone
pip3 install .
cd labop/labop-check
pip3 install .
cd ../container-ontology
pip3 install .

LabOP visualizations currently depend on the graphviz application. To install graphviz, run (per

  • Mac: brew install graphviz
  • Linux: apt-get install graphviz libgraphviz-dev pkg-config
  • Windows: choco install graphviz


To use LabOP in your client application, import the LabOP, UML, and SBOL3 modules:

import labop, uml, sbol3

The LabOP data model is encoded as an ontology using the Web Ontology Language (OWL). (A Turtle serialization of the LabOP ontology can be found in the labop directory, and uses the UML ontology found in the uml directory.) The module's API is dynamically generated directly from this OWL specification immediately upon import of the module into the user's Python environment. The ontology specifies the Python classes, their attributes, their types, and their cardinality.

Working with LabOP Documents

All file I/O is handled through an SBOL Document object. In the following example, we read a file that describes the protocol for an OD calibration using water and LUDOX. The file format can be any RDF format:

doc = sbol3.Document()'test/testfiles/igem_ludox_test.nt')

Once a Document is loaded, you can inspect and manipulate its contents. For example, the following prints an inventory of objects and their metadata:

for obj in doc.objects:

The name attribute is used for human-readable and/or lab-specific identifiers. The identity attribute specifies the unique Uniform Resource Identifier (URI) for each object. The URI can be used to retrieve specific objects from the Document.

ludox = doc.find('')

Creating objects

Every LabOP object is identified by a unique URI. Objects come in two types, "top-level" objects that can stand alone, such as a Protocol or a Primitive, and "child" objects that only make sense within the context of their top-level object, such as a protocol step (ActivityNode) or a Parameter.

When a new "top-level" object is created, the full URI can be either prodiced or automatically generated from a local identifier. Every constructor for a top-level LabOP object takes a local ID or URI as its first argument. If given a local ID, the full URI is then generated from a namespace and the local ID. This local ID must consist of only alphanumeric characters and/or underscores.

When constructing a new Document, the general workflow is as follows. First, set the namespace that governs new objects. Second, create new objects. Finally, add the new object to the Document. For example:

doc = sbol3.Document()
protocol = labop.Protocol('TimeSeries')

Child objects are not named by the user, but receive their names automatically when added to a parent. For example:

step = uml.CallBehaviorAction()
protocol.nodes += [step]
step.identity  #

Note that in many cases, it is better to create child objects by means of helper functions:

four_wells = protocol.primitive_step('PlateCoordinates', coordinates='A2:D2')  # Note: still needs source plate indicated


A Document can be validated as follows:

for issue in doc.validate():

Protocol Execution

A Protocol may be executed an arbitrary amount of times, resulting in a unique history each time that captured by an Execution. Such Executions may record actual times or feedback measurements from instruments during execution.

The ExecutionEngine class is used to carry out a protocol. An ExecutionEngine interprets a Protocol in an application-specific manner using a BehaviorSpecialization object. For example, a BehaviorSpecialization might translate a protocol encoded in LabOP into specific instructions that a particular laboratory's instrumentation or robotics can interpret. Converter tools can also be implemented. Currently the LabOP project includes a Markdown converter that will convert a LabOP-encoded protocol into a human-readable Markdown document. If no BehaviorSpecialization is provided, the default will be used, which is essentially a no-op, but provides some utility for testing and development.

Each protocol execution requires an Agent, used to record the person, laboratory, or machine executing the protocol. An execution may also require input ParameterValues to configure the protocol.

Following is an example execution that converts a protocol for optical density measurement into Markdown format to the file:

agent = sbol3.Agent("2022_Hogwart_iGEM_team")  # Used to describe the person or machine executing the protocol
ee = ExecutionEngine(specializations=[MarkdownSpecialization("")])
parameter_values = [
                        value=sbol3.Measure(600, tyto.OM.nanometer))
execution = ee.execute(protocol, agent, id="OD_measurement", parameter_values=parameter_values)

Example Notebooks

See notebooks for examples of how to use LabOP. An interactive version of the main demonstration notebook notebooks/labop_demo.ipynb is also hosted on Google Collab. The interactive version is shared as view only, but you can make a copy to modify with File -> Save a copy in Drive by saving it on your own Google Drive account.

Strateos Integration

The secrets directory includes a template to configure Strateos credentials. It requires renaming and editing the provided sample. (Please, never commit or share actual credentials!)

cp secrets/strateos_secrets.json.sample secrets/strateos_secrets.json
# Edit contents of secrets/strateos_secrets.json

The secrets for the Strateos API are used by the notebook notebooks/Autoprotocol.ipynb and pytest test/ Additional user permissions may be required to submit runs to Strateos. Please contact Strateos support for assistance.

Generating the LabOP Specification Document

Documentation consisting of LaTeX and PDF Documents that describe the LabOP protocol representation can be generated by running the following script:

python3 doc/