Skip to content

Commit

Permalink
Merge branch 'edge' into js_chew-through-eslint-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
b-cooper committed May 14, 2024
2 parents 7e9cb76 + 1f897cd commit 3a82dd3
Show file tree
Hide file tree
Showing 217 changed files with 3,444 additions and 1,267 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ module.exports = {
importNames: [
'useAllRunsQuery',
'useRunQuery',
'useLastRunCommandKey',
'useAllCommandsQuery',
'useCurrentMaintenanceRun',
'useDeckConfigurationQuery',
'useAllCommandsAsPreSerializedList',
],
message:
'The HTTP hook is deprecated. Utilize the equivalent notification wrapper (useNotifyX) instead.',
'HTTP hook deprecated. Use the equivalent notification wrapper (useNotifyXYZ).',
},
],
},
Expand Down
4 changes: 2 additions & 2 deletions api/docs/v2/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ In each row, you first need to add solution. This will be similar to what you di

.. code-block:: python
left_pipette.transfer(100, reservoir["A2"], row[0], mix_after(3, 50))
left_pipette.transfer(100, reservoir["A2"], row[0], mix_after=(3, 50))
As before, the first argument specifies to transfer 100 µL. The second argument is the source, column 2 of the reservoir. The third argument is the destination, the element at index 0 of the current ``row``. Since Python lists are zero-indexed, but columns on labware start numbering at 1, this will be well A1 on the first time through the loop, B1 the second time, and so on. The fourth argument specifies to mix 3 times with 50 µL of fluid each time.

Expand All @@ -275,7 +275,7 @@ Finally, it’s time to dilute the solution down the row. One approach would be

.. code-block:: python
left_pipette.transfer(100, row[:11], row[1:], mix_after(3, 50))
left_pipette.transfer(100, row[:11], row[1:], mix_after=(3, 50))
There’s some Python shorthand here, so let’s unpack it. You can get a range of indices from a list using the colon ``:`` operator, and omitting it at either end means “from the beginning” or “until the end” of the list. So the source is ``row[:11]``, from the beginning of the row until its 11th item. And the destination is ``row[1:]``, from index 1 (column 2!) until the end. Since both of these lists have 11 items, ``transfer()`` will *step through them in parallel*, and they’re constructed so when the source is 0, the destination is 1; when the source is 1, the destination is 2; and so on. This condenses all of the subsequent transfers down the row into a single line of code.

Expand Down
13 changes: 13 additions & 0 deletions api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
PipetteOverpressureError,
FirmwareUpdateRequiredError,
FailedGripperPickupError,
LiquidNotFoundError,
)

from .subsystem_manager import SubsystemManager
Expand Down Expand Up @@ -1399,6 +1400,18 @@ async def liquid_probe(
for node, point in positions.items():
self._position.update({node: point.motor_position})
self._encoder_position.update({node: point.encoder_position})
if (
head_node not in positions
or positions[head_node].move_ack
== MoveCompleteAck.complete_without_condition
):
raise LiquidNotFoundError(
"Liquid not found during probe.",
{
str(node_to_axis(node)): str(point.motor_position)
for node, point in positions.items()
},
)
return self._position[axis_to_node(Axis.by_mount(mount))]

async def capacitive_probe(
Expand Down
6 changes: 2 additions & 4 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2100,7 +2100,7 @@ async def verify_tip_presence(
real_mount = OT3Mount.from_mount(mount)
status = await self.get_tip_presence_status(real_mount, follow_singular_sensor)
if status != expected:
raise FailedTipStateCheck(expected, status.value)
raise FailedTipStateCheck(expected, status)

async def _force_pick_up_tip(
self, mount: OT3Mount, pipette_spec: TipActionSpec
Expand Down Expand Up @@ -2556,9 +2556,7 @@ async def liquid_probe(
reading from the pressure sensor.
If the move is completed without the specified threshold being triggered, a
LiquidNotFound error will be thrown.
If the threshold is triggered before the minimum z distance has been traveled,
a EarlyLiquidSenseTrigger error will be thrown.
LiquidNotFoundError error will be thrown.
Otherwise, the function will stop moving once the threshold is triggered,
and return the position of the
Expand Down
20 changes: 4 additions & 16 deletions api/src/opentrons/hardware_control/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,25 +694,13 @@ def __init__(
)


class LiquidNotFound(RuntimeError):
"""Error raised if liquid sensing move completes without detecting liquid."""

def __init__(
self, position: Dict[Axis, float], max_z_pos: Dict[Axis, float]
) -> None:
"""Initialize LiquidNotFound error."""
super().__init__(
f"Liquid threshold not found, current_position = {position}"
f"position at max travel allowed = {max_z_pos}"
)


class FailedTipStateCheck(RuntimeError):
"""Error raised if the tip ejector state does not match the expected value."""

def __init__(self, tip_state_type: TipStateType, actual_state: int) -> None:
def __init__(
self, expected_state: TipStateType, actual_state: TipStateType
) -> None:
"""Initialize FailedTipStateCheck error."""
super().__init__(
f"Failed to correctly determine tip state for tip {str(tip_state_type)} "
f"received {bool(actual_state)} but expected {bool(tip_state_type.value)}"
f"Expected tip state {expected_state}, but received {actual_state}."
)
21 changes: 15 additions & 6 deletions api/src/opentrons/protocol_engine/commands/aspirate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
BaseLiquidHandlingResult,
DestinationPositionResult,
)
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
from ..errors.error_occurrence import ErrorOccurrence

from opentrons.hardware_control import HardwareControlAPI

Expand Down Expand Up @@ -40,7 +41,9 @@ class AspirateResult(BaseLiquidHandlingResult, DestinationPositionResult):
pass


class AspirateImplementation(AbstractCommandImpl[AspirateParams, AspirateResult]):
class AspirateImplementation(
AbstractCommandImpl[AspirateParams, SuccessData[AspirateResult, None]]
):
"""Aspirate command implementation."""

def __init__(
Expand All @@ -58,7 +61,9 @@ def __init__(
self._movement = movement
self._command_note_adder = command_note_adder

async def execute(self, params: AspirateParams) -> AspirateResult:
async def execute(
self, params: AspirateParams
) -> SuccessData[AspirateResult, None]:
"""Move to and aspirate from the requested well.
Raises:
Expand Down Expand Up @@ -107,12 +112,16 @@ async def execute(self, params: AspirateParams) -> AspirateResult:
command_note_adder=self._command_note_adder,
)

return AspirateResult(
volume=volume, position=DeckPoint(x=position.x, y=position.y, z=position.z)
return SuccessData(
public=AspirateResult(
volume=volume,
position=DeckPoint(x=position.x, y=position.y, z=position.z),
),
private=None,
)


class Aspirate(BaseCommand[AspirateParams, AspirateResult]):
class Aspirate(BaseCommand[AspirateParams, AspirateResult, ErrorOccurrence]):
"""Aspirate command model."""

commandType: AspirateCommandType = "aspirate"
Expand Down
15 changes: 10 additions & 5 deletions api/src/opentrons/protocol_engine/commands/aspirate_in_place.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
FlowRateMixin,
BaseLiquidHandlingResult,
)
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
from ..errors.error_occurrence import ErrorOccurrence
from ..errors.exceptions import PipetteNotReadyToAspirateError

if TYPE_CHECKING:
Expand All @@ -36,7 +37,7 @@ class AspirateInPlaceResult(BaseLiquidHandlingResult):


class AspirateInPlaceImplementation(
AbstractCommandImpl[AspirateInPlaceParams, AspirateInPlaceResult]
AbstractCommandImpl[AspirateInPlaceParams, SuccessData[AspirateInPlaceResult, None]]
):
"""AspirateInPlace command implementation."""

Expand All @@ -53,7 +54,9 @@ def __init__(
self._hardware_api = hardware_api
self._command_note_adder = command_note_adder

async def execute(self, params: AspirateInPlaceParams) -> AspirateInPlaceResult:
async def execute(
self, params: AspirateInPlaceParams
) -> SuccessData[AspirateInPlaceResult, None]:
"""Aspirate without moving the pipette.
Raises:
Expand All @@ -77,10 +80,12 @@ async def execute(self, params: AspirateInPlaceParams) -> AspirateInPlaceResult:
command_note_adder=self._command_note_adder,
)

return AspirateInPlaceResult(volume=volume)
return SuccessData(public=AspirateInPlaceResult(volume=volume), private=None)


class AspirateInPlace(BaseCommand[AspirateInPlaceParams, AspirateInPlaceResult]):
class AspirateInPlace(
BaseCommand[AspirateInPlaceParams, AspirateInPlaceResult, ErrorOccurrence]
):
"""AspirateInPlace command model."""

commandType: AspirateInPlaceCommandType = "aspirateInPlace"
Expand Down
15 changes: 10 additions & 5 deletions api/src/opentrons/protocol_engine/commands/blow_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
WellLocationMixin,
DestinationPositionResult,
)
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
from ..errors.error_occurrence import ErrorOccurrence

from opentrons.hardware_control import HardwareControlAPI

Expand All @@ -34,7 +35,9 @@ class BlowOutResult(DestinationPositionResult):
pass


class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, BlowOutResult]):
class BlowOutImplementation(
AbstractCommandImpl[BlowOutParams, SuccessData[BlowOutResult, None]]
):
"""BlowOut command implementation."""

def __init__(
Expand All @@ -50,7 +53,7 @@ def __init__(
self._state_view = state_view
self._hardware_api = hardware_api

async def execute(self, params: BlowOutParams) -> BlowOutResult:
async def execute(self, params: BlowOutParams) -> SuccessData[BlowOutResult, None]:
"""Move to and blow-out the requested well."""
x, y, z = await self._movement.move_to_well(
pipette_id=params.pipetteId,
Expand All @@ -63,10 +66,12 @@ async def execute(self, params: BlowOutParams) -> BlowOutResult:
pipette_id=params.pipetteId, flow_rate=params.flowRate
)

return BlowOutResult(position=DeckPoint(x=x, y=y, z=z))
return SuccessData(
public=BlowOutResult(position=DeckPoint(x=x, y=y, z=z)), private=None
)


class BlowOut(BaseCommand[BlowOutParams, BlowOutResult]):
class BlowOut(BaseCommand[BlowOutParams, BlowOutResult, ErrorOccurrence]):
"""Blow-out command model."""

commandType: BlowOutCommandType = "blowout"
Expand Down
15 changes: 10 additions & 5 deletions api/src/opentrons/protocol_engine/commands/blow_out_in_place.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
PipetteIdMixin,
FlowRateMixin,
)
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
from ..errors.error_occurrence import ErrorOccurrence

from opentrons.hardware_control import HardwareControlAPI

Expand All @@ -35,7 +36,7 @@ class BlowOutInPlaceResult(BaseModel):


class BlowOutInPlaceImplementation(
AbstractCommandImpl[BlowOutInPlaceParams, BlowOutInPlaceResult]
AbstractCommandImpl[BlowOutInPlaceParams, SuccessData[BlowOutInPlaceResult, None]]
):
"""BlowOutInPlace command implementation."""

Expand All @@ -50,16 +51,20 @@ def __init__(
self._state_view = state_view
self._hardware_api = hardware_api

async def execute(self, params: BlowOutInPlaceParams) -> BlowOutInPlaceResult:
async def execute(
self, params: BlowOutInPlaceParams
) -> SuccessData[BlowOutInPlaceResult, None]:
"""Blow-out without moving the pipette."""
await self._pipetting.blow_out_in_place(
pipette_id=params.pipetteId, flow_rate=params.flowRate
)

return BlowOutInPlaceResult()
return SuccessData(public=BlowOutInPlaceResult(), private=None)


class BlowOutInPlace(BaseCommand[BlowOutInPlaceParams, BlowOutInPlaceResult]):
class BlowOutInPlace(
BaseCommand[BlowOutInPlaceParams, BlowOutInPlaceResult, ErrorOccurrence]
):
"""BlowOutInPlace command model."""

commandType: BlowOutInPlaceCommandType = "blowOutInPlace"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
from opentrons.hardware_control.instruments.ot3.instrument_calibration import (
GripperCalibrationOffset,
)
from opentrons.protocol_engine.commands.command import (
AbstractCommandImpl,
BaseCommand,
BaseCommandCreate,
)
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
from ...errors.error_occurrence import ErrorOccurrence
from opentrons.protocol_engine.types import Vec3f
from opentrons.protocol_engine.resources import ensure_ot3_hardware

Expand Down Expand Up @@ -74,7 +71,9 @@ class CalibrateGripperResult(BaseModel):


class CalibrateGripperImplementation(
AbstractCommandImpl[CalibrateGripperParams, CalibrateGripperResult]
AbstractCommandImpl[
CalibrateGripperParams, SuccessData[CalibrateGripperResult, None]
]
):
"""The implementation of a `calibrateGripper` command."""

Expand All @@ -86,7 +85,9 @@ def __init__(
) -> None:
self._hardware_api = hardware_api

async def execute(self, params: CalibrateGripperParams) -> CalibrateGripperResult:
async def execute(
self, params: CalibrateGripperParams
) -> SuccessData[CalibrateGripperResult, None]:
"""Execute a `calibrateGripper` command.
1. Move from the current location to the calibration area on the deck.
Expand Down Expand Up @@ -118,11 +119,14 @@ async def execute(self, params: CalibrateGripperParams) -> CalibrateGripperResul
)
calibration_data = result

return CalibrateGripperResult.construct(
jawOffset=Vec3f.construct(
x=probe_offset.x, y=probe_offset.y, z=probe_offset.z
return SuccessData(
public=CalibrateGripperResult.construct(
jawOffset=Vec3f.construct(
x=probe_offset.x, y=probe_offset.y, z=probe_offset.z
),
savedCalibration=calibration_data,
),
savedCalibration=calibration_data,
private=None,
)

@staticmethod
Expand All @@ -135,7 +139,9 @@ def _convert_to_hw_api_probe(
return HWAPIGripperProbe.REAR


class CalibrateGripper(BaseCommand[CalibrateGripperParams, CalibrateGripperResult]):
class CalibrateGripper(
BaseCommand[CalibrateGripperParams, CalibrateGripperResult, ErrorOccurrence]
):
"""A `calibrateGripper` command."""

commandType: CalibrateGripperCommandType = "calibration/calibrateGripper"
Expand Down
Loading

0 comments on commit 3a82dd3

Please sign in to comment.