Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-engine): Support loading pipettes and labware from JSON protocols #7950

Merged
merged 22 commits into from
Jun 17, 2021

Conversation

SyntaxColoring
Copy link
Contributor

@SyntaxColoring SyntaxColoring commented Jun 15, 2021

Overview

When a JSON protocol is uploaded through the experimental HTTP API, to be run through protocol engine, implement the missing parts of loading the pipettes and labware that the JSON protocol uses. Closes #7946.

Changelog

Main changes:

  • Changed CommandTranslator to take in an entire protocol at once, instead of going command-by-command.
    • Changed calling code and its tests accordingly.
  • Gave CommandTranslator the ability to translate a JSON protocol's choices of pipettes and labware into Protocol Engine LoadPipetteRequests, AddLabwareDefinitionRequests, and LoadLabwareRequests.

Also:

  • Clarified that LoadPipetteRequest.pipetteName is the pipette load name, as opposed to the model name or something.
  • Left a maybe unnecessary comment in opentrons/protocols/models/__init.py__ describing when (I think) it should re-export things from its child submodules. I had gone down an unproductive path adding re-exports for everything I could possibly need from that tree.

Deferred work

Other stuff discussed in in-person reviews

  • @sanni-t and I considered renaming CommandTranslator to ProtocolTranslator, since it now takes in and translates an entire JSON protocol at once, rather than going command-by-command. This could have been necessary if we chose a testing approach where command translation is a separate class from protocol translation, but we didn't, so this renaming doesn't feel worthwhile to me anymore.

Review requests

I would focus on the production code, since we know the tests to be messy and we already have a good path in mind to fix them.

Risk assessment

Low. Only used in our experimental Protocol Engine work, behind a feature flag.

@codecov
Copy link

codecov bot commented Jun 15, 2021

Codecov Report

Merging #7950 (5f3187f) into edge (1061b5b) will increase coverage by 0.13%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             edge    #7950      +/-   ##
==========================================
+ Coverage   85.93%   86.06%   +0.13%     
==========================================
  Files         348      348              
  Lines       21232    21471     +239     
==========================================
+ Hits        18245    18479     +234     
- Misses       2987     2992       +5     
Impacted Files Coverage Δ
robot-server/robot_server/router.py 90.47% <0.00%> (-2.39%) ⬇️
opentrons/protocol_engine/state/pipettes.py 96.87% <0.00%> (-1.74%) ⬇️
opentrons/protocols/models/__init__.py 100.00% <0.00%> (ø)
opentrons/file_runner/json_file_runner.py 100.00% <0.00%> (ø)
opentrons/protocol_engine/state/motion.py 100.00% <0.00%> (ø)
opentrons/protocol_engine/state/labware.py 100.00% <0.00%> (ø)
opentrons/protocol_engine/state/geometry.py 100.00% <0.00%> (ø)
...er/robot_server/service/legacy/routers/__init__.py 100.00% <0.00%> (ø)
opentrons/protocol_engine/state/state_store.py 98.14% <0.00%> (+0.18%) ⬆️
robot-server/robot_server/app.py 94.23% <0.00%> (+2.80%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1061b5b...5f3187f. Read the comment docs.

@mcous
Copy link
Contributor

mcous commented Jun 17, 2021

Just did some real world testing, and it's looking like this is fundamentally working! We've got a little issue with the command state, but otherwise this looks like it's doing the thing 🎉

As we've just implemented things in pipette and labware translation, yes, these IDs are the same.
* Revert some thoughtless re-exports I made earlier in this PR.
* Say what I think actually should be re-exported here, so I don't make the same mistake again.
@SyntaxColoring SyntaxColoring marked this pull request as ready for review June 17, 2021 19:06
@SyntaxColoring SyntaxColoring requested a review from a team as a code owner June 17, 2021 19:06
@SyntaxColoring SyntaxColoring marked this pull request as draft June 17, 2021 19:41
@mcous mcous added the robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience). label Jun 17, 2021
@mcous mcous added the protocol-engine Ticket related to the Protocol Engine project and associated HTTP APIs label Jun 17, 2021
@SyntaxColoring SyntaxColoring marked this pull request as ready for review June 17, 2021 20:54
Copy link
Contributor

@mcous mcous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some discussion points, but covered most of this on chat. Got a few discussion points below, but otherwise this looks to be fundamentally working and the TODOs check out

Comment on lines +1 to +7
# Convenience re-exports of models that are especially common or important.
# More detailed sub-models are always available through the underlying
# submodules.
#
# If re-exporting something, its name should still make sense when it's separatred
# from the name of its parent submodule. e.g. re-exporting models.json_protocol.Labware
# as models.Labware could be confusing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, this is referring to the from .json_protocol import Model as JsonProtocol re-export business? Agree that should be avoided

Copy link
Contributor Author

@SyntaxColoring SyntaxColoring Jun 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not totally sure we're talking about the same thing.

I had gone down an unproductive path of adding re-exports for everything I could possibly need from json_protocol and labware_definitions to this __init__.py. I tried re-exporting json_protocol.Labware, json_protocol.AllCommands, and so on.

Somewhere in the middle of this PR, I realized that this would cause confusing naming problems. For example, models.Labware sounds like it's about Opentrons labware definitions in general, but as a re-export of json_protocols.Labware, it's actually a very specific JSON protocol thing.

So this comment is meant to say, "I know we're re-exporting some things here at the top level, but don't get tempted into doing this for absolutely everything. Here's where it does and doesn't make sense."

json_protocol.Model is funky but I don't think the concern is specific to it.

PickUpTipRequest, DropTipRequest
)
from opentrons.protocols.models import json_protocol as models
import opentrons.types
Copy link
Contributor

@mcous mcous Jun 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find import foo.bar to be very confusing; it's was non-obvious to me that you then proceed to use foo.bar in the code.

Given that we use exactly two structures from here, I would've written this as:

from opentrons.types import DeckSlotName, MountType

Mostly because I'm lazy and it's less typing everywhere, and doesn't feel to me like it's a loss in understanding because the name is consistent everywhere and most of us are working in editors / IDEs with type info + click-to-follow

Translate a PD/JSON protocol to Protocol Engine commands.
def translate(self, protocol: models.JsonProtocol) -> PECommands:
"""Return all Protocol Engine commands required to run the given protocol."""
result: List[pe.commands.CommandRequestType] = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pe.commands.WhateverThing makes me feel a little like we're locking into the internal shape of the protocol_engine module. It sort of makes me think that this translator belongs in the protocol_engine module itself (perhaps in clients or something

Copy link
Contributor Author

@SyntaxColoring SyntaxColoring Jun 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we mention commands over and over every time we type pe.commands.WhateverThing, as opposed to once at the top of the file like from protocol_engine.commands import ...?

That's true.

I think in this particular case, it gets resolved if we do from protocol_engine import commands as pe_commands, as you suggested and as I've just written about in Slack.

This also brings up a second discussion of whether submodule names are / can be / should be part of the whole collective package's stable interface. I'll write about this separately.

@SyntaxColoring SyntaxColoring merged commit e43c80f into edge Jun 17, 2021
@mcous mcous deleted the commandtranslator_pipettes_and_labware branch June 17, 2021 22:05
@SyntaxColoring
Copy link
Contributor Author

SyntaxColoring commented Jun 17, 2021

Merging this now to make it easier to test running protocols on robots (yay!). But feel free to keep leaving comments here (and maybe ping me) for stuff to clarify/fix/change in a follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
protocol-engine Ticket related to the Protocol Engine project and associated HTTP APIs robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CommandTranslator should support pipette and labware load commands
3 participants