Skip to content

Commit

Permalink
feat(api): warn tc-lid/gantry collision in simulation (#4394)
Browse files Browse the repository at this point in the history
If a given protocol would target the labware loaded into a thermocycler module, while that module is known to be closed, simulation will fail with a helpful message.

Closes #4044
  • Loading branch information
b-cooper authored Nov 8, 2019
1 parent ce023a1 commit b22a3b3
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 12 deletions.
2 changes: 1 addition & 1 deletion api/docs/v2/new_protocol_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Modules

.. autoclass:: opentrons.protocol_api.contexts.ThermocyclerContext
:members:
:exclude-members: total_step_count, current_cycle_index, total_cycle_count, hold_time, ramp_rate, current_step_index
:exclude-members: total_step_count, current_cycle_index, total_cycle_count, hold_time, ramp_rate, current_step_index, flag_unsafe_move
:inherited-members:


Expand Down
15 changes: 15 additions & 0 deletions api/src/opentrons/protocol_api/contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,10 @@ def move_to(self, location: types.Location, force_direct: bool = False,
self._mount, critical_point=cp_override),
from_lw)

for mod in self._ctx._modules:
if isinstance(mod, ThermocyclerContext):
mod.flag_unsafe_move(to_loc=location, from_loc=from_loc)

moves = geometry.plan_moves(from_loc, location, self._ctx.deck,
force_direct=force_direct,
minimum_z_height=minimum_z_height)
Expand Down Expand Up @@ -2166,6 +2170,17 @@ def _prepare_for_lid_move(self):
z=high_point[Axis.by_mount(instr._mount)])
instr.move_to(types.Location(safe_point, None), force_direct=True)

def flag_unsafe_move(self,
to_loc: types.Location,
from_loc: types.Location):
to_lw, to_well = geometry.split_loc_labware(to_loc)
from_lw, from_well = geometry.split_loc_labware(from_loc)
if (self.labware is to_lw or self.labware is from_lw) and \
self.lid_position == 'closed':
raise RuntimeError(
"Cannot move to labware loaded in Thermocycler"
" when lid is closed")

@cmds.publish.both(command=cmds.thermocycler_open)
@requires_version(2, 0)
def open_lid(self):
Expand Down
23 changes: 12 additions & 11 deletions api/src/opentrons/protocol_api/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ def max_many(*args):
return functools.reduce(max, args[1:], args[0])


def split_loc_labware(
loc: types.Location) -> Tuple[Optional[Labware], Optional[Well]]:
if isinstance(loc.labware, Labware):
return loc.labware, None
elif isinstance(loc.labware, Well):
return loc.labware.parent, loc.labware
else:
return None, None


def plan_moves(
from_loc: types.Location,
to_loc: types.Location,
Expand Down Expand Up @@ -54,19 +64,10 @@ def plan_moves(

assert minimum_z_height is None or minimum_z_height >= 0.0

def _split_loc_labware(
loc: types.Location) -> Tuple[Optional[Labware], Optional[Well]]:
if isinstance(loc.labware, Labware):
return loc.labware, None
elif isinstance(loc.labware, Well):
return loc.labware.parent, loc.labware
else:
return None, None

to_point = to_loc.point
to_lw, to_well = _split_loc_labware(to_loc)
to_lw, to_well = split_loc_labware(to_loc)
from_point = from_loc.point
from_lw, from_well = _split_loc_labware(from_loc)
from_lw, from_well = split_loc_labware(from_loc)
dest_quirks = quirks_from_any_parent(to_lw)
from_quirks = quirks_from_any_parent(from_lw)
from_center = 'centerMultichannelOnWells' in from_quirks
Expand Down

0 comments on commit b22a3b3

Please sign in to comment.