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(hardware): refactor tool_sensors to simplify and remove csvs #16462

Merged
merged 11 commits into from
Oct 21, 2024
9 changes: 9 additions & 0 deletions api/src/opentrons/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,15 @@ class ConfigElement(NamedTuple):
" absolute path, it will be used directly. If it is a "
"relative path it will be relative to log_dir",
),
ConfigElement(
"sensor_log_file",
"Sensor Log File",
Path("logs") / "sensor.log",
ConfigElementType.FILE,
"The location of the file to save sensor logs to. If this is an"
" absolute path, it will be used directly. If it is a "
"relative path it will be relative to log_dir",
),
ConfigElement(
"serial_log_file",
"Serial Log File",
Expand Down
36 changes: 0 additions & 36 deletions api/src/opentrons/config/defaults_ot3.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
LiquidProbeSettings,
ZSenseSettings,
EdgeSenseSettings,
OutputOptions,
)


Expand All @@ -27,13 +26,11 @@
plunger_speed=15,
plunger_impulse_time=0.2,
sensor_threshold_pascals=15,
output_option=OutputOptions.sync_buffer_to_csv,
aspirate_while_sensing=False,
z_overlap_between_passes_mm=0.1,
plunger_reset_offset=2.0,
samples_for_baselining=20,
sample_time_sec=0.004,
data_files={InstrumentProbeType.PRIMARY: "/data/pressure_sensor_data.csv"},
)

DEFAULT_CALIBRATION_SETTINGS: Final[OT3CalibrationSettings] = OT3CalibrationSettings(
Expand All @@ -43,7 +40,6 @@
max_overrun_distance_mm=5.0,
speed_mm_per_s=1.0,
sensor_threshold_pf=3.0,
output_option=OutputOptions.sync_only,
),
),
edge_sense=EdgeSenseSettings(
Expand All @@ -54,7 +50,6 @@
max_overrun_distance_mm=0.5,
speed_mm_per_s=1,
sensor_threshold_pf=3.0,
output_option=OutputOptions.sync_only,
),
search_initial_tolerance_mm=12.0,
search_iteration_limit=8,
Expand Down Expand Up @@ -195,23 +190,6 @@
)


def _build_output_option_with_default(
from_conf: Any, default: OutputOptions
) -> OutputOptions:
if from_conf is None:
return default
else:
if isinstance(from_conf, OutputOptions):
return from_conf
else:
try:
enumval = OutputOptions[from_conf]
except KeyError: # not an enum entry
return default
else:
return enumval


def _build_log_files_with_default(
from_conf: Any,
default: Optional[Dict[InstrumentProbeType, str]],
Expand Down Expand Up @@ -316,24 +294,12 @@ def _build_default_cap_pass(
sensor_threshold_pf=from_conf.get(
"sensor_threshold_pf", default.sensor_threshold_pf
),
output_option=from_conf.get("output_option", default.output_option),
)


def _build_default_liquid_probe(
from_conf: Any, default: LiquidProbeSettings
) -> LiquidProbeSettings:
output_option = _build_output_option_with_default(
from_conf.get("output_option", None), default.output_option
)
data_files: Optional[Dict[InstrumentProbeType, str]] = None
if (
output_option is OutputOptions.sync_buffer_to_csv
or output_option is OutputOptions.stream_to_csv
):
data_files = _build_log_files_with_default(
from_conf.get("data_files", None), default.data_files
)
return LiquidProbeSettings(
mount_speed=from_conf.get("mount_speed", default.mount_speed),
plunger_speed=from_conf.get("plunger_speed", default.plunger_speed),
Expand All @@ -343,7 +309,6 @@ def _build_default_liquid_probe(
sensor_threshold_pascals=from_conf.get(
"sensor_threshold_pascals", default.sensor_threshold_pascals
),
output_option=from_conf.get("output_option", default.output_option),
aspirate_while_sensing=from_conf.get(
"aspirate_while_sensing", default.aspirate_while_sensing
),
Expand All @@ -357,7 +322,6 @@ def _build_default_liquid_probe(
"samples_for_baselining", default.samples_for_baselining
),
sample_time_sec=from_conf.get("sample_time_sec", default.sample_time_sec),
data_files=data_files,
)


Expand Down
19 changes: 2 additions & 17 deletions api/src/opentrons/config/types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from enum import Enum
from dataclasses import dataclass, asdict, fields
from typing import Dict, Tuple, TypeVar, Generic, List, cast, Optional
from typing import Dict, Tuple, TypeVar, Generic, List, cast
from typing_extensions import TypedDict, Literal
from opentrons.hardware_control.types import OT3AxisKind, InstrumentProbeType
from opentrons.hardware_control.types import OT3AxisKind


class AxisDict(TypedDict):
Expand Down Expand Up @@ -103,25 +103,12 @@ def by_gantry_load(
)


class OutputOptions(int, Enum):
"""Specifies where we should report sensor data to during a sensor pass."""

stream_to_csv = 0x1 # compile sensor data stream into a csv file, in addition to can_bus_only behavior
sync_buffer_to_csv = 0x2 # collect sensor data on pipette mcu, then stream to robot server and compile into a csv file, in addition to can_bus_only behavior
can_bus_only = (
0x4 # stream sensor data over CAN bus, in addition to sync_only behavior
)
sync_only = 0x8 # trigger pipette sync line upon sensor's detection of something


@dataclass(frozen=True)
class CapacitivePassSettings:
prep_distance_mm: float
max_overrun_distance_mm: float
speed_mm_per_s: float
sensor_threshold_pf: float
output_option: OutputOptions
data_files: Optional[Dict[InstrumentProbeType, str]] = None


@dataclass(frozen=True)
Expand All @@ -135,13 +122,11 @@ class LiquidProbeSettings:
plunger_speed: float
plunger_impulse_time: float
sensor_threshold_pascals: float
output_option: OutputOptions
aspirate_while_sensing: bool
z_overlap_between_passes_mm: float
plunger_reset_offset: float
samples_for_baselining: int
sample_time_sec: float
data_files: Optional[Dict[InstrumentProbeType, str]]


@dataclass(frozen=True)
Expand Down
11 changes: 6 additions & 5 deletions api/src/opentrons/hardware_control/backends/flex_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from opentrons_shared_data.pipette.types import (
PipetteName,
)
from opentrons.config.types import GantryLoad, OutputOptions
from opentrons.config.types import GantryLoad
from opentrons.hardware_control.types import (
BoardRevision,
Axis,
Expand All @@ -38,6 +38,8 @@
StatusBarState,
)
from opentrons.hardware_control.module_control import AttachedModulesControl
from opentrons_hardware.firmware_bindings.constants import SensorId
from opentrons_hardware.sensors.types import SensorDataType
from ..dev_types import OT3AttachedInstruments
from .types import HWStopCondition

Expand Down Expand Up @@ -152,10 +154,11 @@ async def liquid_probe(
threshold_pascals: float,
plunger_impulse_time: float,
num_baseline_reads: int,
output_format: OutputOptions = OutputOptions.can_bus_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
force_both_sensors: bool = False,
response_queue: Optional[
asyncio.Queue[dict[SensorId, list[SensorDataType]]]
Copy link
Member

Choose a reason for hiding this comment

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

if we're going to use the lower case versions here we should change the rest of the file imo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure what that means

Copy link
Member

Choose a reason for hiding this comment

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

for the types - dict instead of typing.Dict

] = None,
) -> float:
...

Expand Down Expand Up @@ -371,8 +374,6 @@ async def capacitive_probe(
speed_mm_per_s: float,
sensor_threshold_pf: float,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
output_format: OutputOptions = OutputOptions.sync_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
) -> bool:
...

Expand Down
57 changes: 7 additions & 50 deletions api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
Union,
Mapping,
)
from opentrons.config.types import OT3Config, GantryLoad, OutputOptions
from opentrons.config.types import OT3Config, GantryLoad
from opentrons.config import gripper_config
from .ot3utils import (
axis_convert,
Expand Down Expand Up @@ -102,7 +102,9 @@
NodeId,
PipetteName as FirmwarePipetteName,
ErrorCode,
SensorId,
)
from opentrons_hardware.sensors.types import SensorDataType
from opentrons_hardware.firmware_bindings.messages.message_definitions import (
StopRequest,
)
Expand Down Expand Up @@ -1368,28 +1370,14 @@ async def liquid_probe(
threshold_pascals: float,
plunger_impulse_time: float,
num_baseline_reads: int,
output_option: OutputOptions = OutputOptions.can_bus_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
force_both_sensors: bool = False,
response_queue: Optional[
asyncio.Queue[dict[SensorId, list[SensorDataType]]]
] = None,
) -> float:
head_node = axis_to_node(Axis.by_mount(mount))
tool = sensor_node_for_pipette(OT3Mount(mount.value))
csv_output = bool(output_option.value & OutputOptions.stream_to_csv.value)
sync_buffer_output = bool(
output_option.value & OutputOptions.sync_buffer_to_csv.value
)
can_bus_only_output = bool(
output_option.value & OutputOptions.can_bus_only.value
)
data_files_transposed = (
None
if data_files is None
else {
sensor_id_for_instrument(probe): data_files[probe]
for probe in data_files.keys()
}
)
positions = await liquid_probe(
messenger=self._messenger,
tool=tool,
Expand All @@ -1400,12 +1388,9 @@ async def liquid_probe(
threshold_pascals=threshold_pascals,
plunger_impulse_time=plunger_impulse_time,
num_baseline_reads=num_baseline_reads,
csv_output=csv_output,
sync_buffer_output=sync_buffer_output,
can_bus_only_output=can_bus_only_output,
data_files=data_files_transposed,
sensor_id=sensor_id_for_instrument(probe),
force_both_sensors=force_both_sensors,
response_queue=response_queue,
)
for node, point in positions.items():
self._position.update({node: point.motor_position})
Expand All @@ -1432,41 +1417,13 @@ async def capacitive_probe(
speed_mm_per_s: float,
sensor_threshold_pf: float,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
output_option: OutputOptions = OutputOptions.sync_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
) -> bool:
if output_option == OutputOptions.sync_buffer_to_csv:
assert (
self._subsystem_manager.device_info[
SubSystem.of_mount(mount)
].revision.tertiary
== "1"
)
csv_output = bool(output_option.value & OutputOptions.stream_to_csv.value)
sync_buffer_output = bool(
output_option.value & OutputOptions.sync_buffer_to_csv.value
)
can_bus_only_output = bool(
output_option.value & OutputOptions.can_bus_only.value
)
data_files_transposed = (
None
if data_files is None
else {
sensor_id_for_instrument(probe): data_files[probe]
for probe in data_files.keys()
}
)
status = await capacitive_probe(
messenger=self._messenger,
tool=sensor_node_for_mount(mount),
mover=axis_to_node(moving),
distance=distance_mm,
mount_speed=speed_mm_per_s,
csv_output=csv_output,
sync_buffer_output=sync_buffer_output,
can_bus_only_output=can_bus_only_output,
data_files=data_files_transposed,
sensor_id=sensor_id_for_instrument(probe),
relative_threshold_pf=sensor_threshold_pf,
)
Expand Down
12 changes: 6 additions & 6 deletions api/src/opentrons/hardware_control/backends/ot3simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
Mapping,
)

from opentrons.config.types import OT3Config, GantryLoad, OutputOptions
from opentrons.config.types import OT3Config, GantryLoad
from opentrons.config import gripper_config

from opentrons.hardware_control.module_control import AttachedModulesControl
Expand Down Expand Up @@ -63,7 +63,8 @@
from opentrons.util.async_helpers import ensure_yield
from .types import HWStopCondition
from .flex_protocol import FlexBackend

from opentrons_hardware.firmware_bindings.constants import SensorId
from opentrons_hardware.sensors.types import SensorDataType

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -347,10 +348,11 @@ async def liquid_probe(
threshold_pascals: float,
plunger_impulse_time: float,
num_baseline_reads: int,
output_format: OutputOptions = OutputOptions.can_bus_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
force_both_sensors: bool = False,
response_queue: Optional[
asyncio.Queue[dict[SensorId, list[SensorDataType]]]
] = None,
) -> float:
z_axis = Axis.by_mount(mount)
pos = self._position
Expand Down Expand Up @@ -750,8 +752,6 @@ async def capacitive_probe(
speed_mm_per_s: float,
sensor_threshold_pf: float,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
output_format: OutputOptions = OutputOptions.sync_only,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
) -> bool:
self._position[moving] += distance_mm
return True
Expand Down
Loading
Loading