Skip to content

Commit

Permalink
feat(api): allow labware calibration on non liquid handling events
Browse files Browse the repository at this point in the history
closes #7800
  • Loading branch information
Laura Cox authored and Laura Cox committed May 13, 2021
1 parent ccfd044 commit aef1076
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 8 deletions.
15 changes: 15 additions & 0 deletions api/src/opentrons/commands/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,18 @@ def drop_tip(
'text': text
}
}


def move_to(
instrument: InstrumentContext,
location: Union[Location, Well]) -> command_types.MoveToCommand:
location_text = stringify_location(location)
text = 'Moving to {location}'.format(location=location_text)
return {
'name': command_types.MOVE_TO,
'payload': {
'instrument': instrument,
'location': location,
'text': text
}
}
15 changes: 15 additions & 0 deletions api/src/opentrons/commands/paired_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,18 @@ def paired_drop_tip(
'text': text
}
}


def paired_move_to(
instruments: Apiv2Instruments,
locations: Apiv2Locations, pub_type: str) -> command_types.MoveToCommand:
location_text = combine_locations(locations)
text = f'{pub_type}: Moving to {location_text}'
return {
'name': command_types.MOVE_TO,
'payload': {
'instruments': instruments,
'locations': locations,
'text': text
}
}
27 changes: 24 additions & 3 deletions api/src/opentrons/commands/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
AIR_GAP: Final = 'command.AIR_GAP'
TOUCH_TIP: Final = 'command.TOUCH_TIP'
RETURN_TIP: Final = 'command.RETURN_TIP'
MOVE_TO: Final = 'command.MOVE_TO'

# Modules #

Expand Down Expand Up @@ -450,6 +451,21 @@ class DropTipCommand(TypedDict):
payload: Union[DropTipCommandPayload, PairedDropTipCommandPayload]


class MoveToCommand(TypedDict):
name: Literal['command.MOVE_TO']
payload: Union[MoveToCommandPayload, PairedMoveToCommandPayload]


class MoveToCommandPayload(
TextOnlyPayload, SingleLocationPayload, SingleInstrumentPayload):
pass


class PairedMoveToCommandPayload(
TextOnlyPayload, MultiLocationPayload, MultiInstrumentPayload):
pass


Command = Union[
DropTipCommand, PickUpTipCommand, ReturnTipCommand, AirGapCommand,
TouchTipCommand, BlowOutCommand, MixCommand, TransferCommand,
Expand All @@ -463,7 +479,7 @@ class DropTipCommand(TypedDict):
TempdeckDeactivateCommand, TempdeckAwaitTempCommand,
TempdeckSetTempCommand, MagdeckCalibrateCommand, MagdeckDisengageCommand,
MagdeckEngageCommand, ResumeCommand, PauseCommand, DelayCommand,
CommentCommand]
CommentCommand, MoveToCommand]


CommandPayload = Union[
Expand Down Expand Up @@ -492,7 +508,8 @@ class DropTipCommand(TypedDict):
ThermocyclerSetBlockTempCommandPayload,
TempdeckAwaitTempCommandPayload,
TempdeckSetTempCommandPayload,
PauseCommandPayload, DelayCommandPayload
PauseCommandPayload, DelayCommandPayload,
MoveToCommandPayload, PairedMoveToCommandPayload
]


Expand All @@ -510,6 +527,10 @@ class CommandMessageFields(CommandMessageMeta, CommandMessageSequence):
pass


class MoveToMessage(CommandMessageFields, MoveToCommand):
pass


class DropTipMessage(CommandMessageFields, DropTipCommand):
pass

Expand Down Expand Up @@ -673,4 +694,4 @@ class CommentMessage(CommandMessageFields, CommentCommand):
ThermocyclerExecuteProfileMessage, ThermocyclerSetBlockTempMessage,
ThermocyclerOpenMessage, TempdeckSetTempMessage, TempdeckDeactivateMessage,
MagdeckEngageMessage, MagdeckDisengageMessage, MagdeckCalibrateMessage,
CommentMessage, DelayMessage, PauseMessage, ResumeMessage]
CommentMessage, DelayMessage, PauseMessage, ResumeMessage, MoveToMessage]
4 changes: 4 additions & 0 deletions api/src/opentrons/protocol_api/instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -1110,12 +1110,16 @@ def move_to(self,
if isinstance(mod, ThermocyclerContext):
mod.flag_unsafe_move(to_loc=location, from_loc=from_loc)

do_publish(self.broker, cmds.move_to, self.move_to, 'before',
None, None, self, location or self._ctx.location_cache)
self._implementation.move_to(
location=location,
force_direct=force_direct,
minimum_z_height=minimum_z_height,
speed=speed
)
do_publish(self.broker, cmds.move_to, self.move_to, 'after',
None, None, self, location or self._ctx.location_cache)
return self

@property # type: ignore
Expand Down
8 changes: 8 additions & 0 deletions api/src/opentrons/protocol_api/paired_instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,16 @@ def move_to(self, location: types.Location, force_direct: bool = False,
to limit individual axis speeds, you can use
:py:attr:`.ProtocolContext.max_speeds`.
"""
instruments = list(self._instruments.values())
locations: Optional[List] = None
if location:
locations = self._get_locations(location)
publish_paired(self.broker, cmds.paired_move_to,
'before', None, instruments, locations)
self.paired_instrument_obj.move_to(
location, force_direct, minimum_z_height, speed)
publish_paired(self.broker, cmds.paired_move_to,
'after', None, instruments, locations)
return self

def _next_available_tip(self) -> Tuple[Labware, Well]:
Expand Down
25 changes: 23 additions & 2 deletions api/tests/opentrons/api/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ def run(ctx):
contents=proto)


@pytest.mark.api2_only
async def test_session_extra_labware(main_router, get_labware_fixture,
virtual_smoothie_env):
proto = '''
Expand Down Expand Up @@ -205,7 +204,6 @@ def run(ctx):
contents=proto)


@pytest.mark.api2_only
async def test_session_bundle(main_router, get_bundle_fixture,
virtual_smoothie_env):
bundle = get_bundle_fixture('simple_bundle')
Expand Down Expand Up @@ -257,6 +255,29 @@ def run(ctx):
assert 'p10_single_v1' in [pip.name for pip in session2.instruments]


async def test_session_move_to_labware(main_router,
virtual_smoothie_env):
proto = '''
metadata = {"apiLevel": "2.0"}
def run(ctx):
rack1 = ctx.load_labware('opentrons_96_tiprack_300ul', '1')
rack2 = ctx.load_labware('opentrons_96_tiprack_300ul', '2')
left = ctx.load_instrument('p300_single', 'left', tip_racks=[rack1])
plate = ctx.load_labware('corning_96_wellplate_360ul_flat', '4')
left.pick_up_tip()
left.move_to(plate['A1'].top())
left.move_to(plate['A2'].top())
left.drop_tip()
'''
session = main_router.session_manager.create('dummy-pipette',
proto)
assert 'p300_single_v1' in [pip.name for pip in session.instruments]

# Labware that does not have a liquid handling event, but is interacted
# with using a pipette should still show up in the list of labware.
assert 'corning_96_wellplate_360ul_flat' in [lw.type for lw in session.containers]


async def test_session_run_concurrently(
main_router,
get_labware_fixture,
Expand Down
3 changes: 0 additions & 3 deletions api/tests/opentrons/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,6 @@ def model(request, hardware, loop):
# Use with pytest.mark.parametrize(’labware’, [some-labware-name])
# to have a different labware loaded as .container. If not passed,
# defaults to the version-appropriate way to do 96 flat
if request.node.get_closest_marker('api2_only')\
and request.param != build_v2_model:
pytest.skip('only works with hardware controller')
try:
lw_name = request.getfixturevalue('labware_name')
except Exception:
Expand Down

0 comments on commit aef1076

Please sign in to comment.