Skip to content

Commit

Permalink
tip overlap by dict fix for v3_6 p1000 and engine updates to reflect …
Browse files Browse the repository at this point in the history
…arch change
  • Loading branch information
CaseyBatten committed May 17, 2024
1 parent 6004a9a commit 350ebd0
Show file tree
Hide file tree
Showing 32 changed files with 657 additions and 316 deletions.
2 changes: 1 addition & 1 deletion api/src/opentrons/hardware_control/dev_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class PipetteDict(InstrumentDict):
current_volume: float
tip_length: float
working_volume: float
tip_overlap: float
tip_overlap: Dict[str, float]
available_volume: float
return_tip_height: float
default_aspirate_flow_rates: Dict[str, float]
Expand Down
60 changes: 38 additions & 22 deletions api/src/opentrons/hardware_control/instruments/ot2/pipette.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ def __init__(
self._active_tip_settings.default_blowout_flowrate.default
)

self._tip_overlap = self.get_nominal_tip_overlap_by_configuration()
self._tip_overlap_dictionary = (
self.get_nominal_tip_overlap_dictionary_by_configuration()
)

if use_old_aspiration_functions:
self._pipetting_function_version = PIPETTING_FUNCTION_FALLBACK_VERSION
Expand Down Expand Up @@ -222,8 +224,8 @@ def pipette_offset(self) -> PipetteOffsetByPipetteMount:
return self._pipette_offset

@property
def tip_overlap(self) -> float:
return self._tip_overlap
def tip_overlap(self) -> Dict[str, float]:
return self._tip_overlap_dictionary

@property
def channels(self) -> pip_types.PipetteChannelType:
Expand Down Expand Up @@ -296,7 +298,9 @@ def reset_state(self) -> None:
self.active_tip_settings.default_blowout_flowrate.default
)

self._tip_overlap = self.get_nominal_tip_overlap_by_configuration()
self._tip_overlap_dictionary = (
self.get_nominal_tip_overlap_dictionary_by_configuration()
)

self._nozzle_manager = (
nozzle_manager.NozzleConfigurationManager.build_from_config(self._config)
Expand Down Expand Up @@ -552,9 +556,17 @@ def get_pick_up_speed_by_configuration(
"Pick up tip speed request error. Nozzle Configuration does not match any approved map layout for the current pipette."
)

return config.configuration_by_nozzle_map[approved_map][
pip_types.PipetteTipType(self._liquid_class.max_volume).name
].speed
try:
return config.configuration_by_nozzle_map[approved_map][
pip_types.PipetteTipType(self._liquid_class.max_volume).name
].speed
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.speed
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)

def get_pick_up_distance_by_configuration(
self,
Expand All @@ -566,7 +578,7 @@ def get_pick_up_distance_by_configuration(
return config.configuration_by_nozzle_map[approved_map][
pip_types.PipetteTipType(self._liquid_class.max_volume).name
].distance
except:
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.distance
Expand All @@ -584,17 +596,17 @@ def get_pick_up_current_by_configuration(
return config.configuration_by_nozzle_map[approved_map][
pip_types.PipetteTipType(self._liquid_class.max_volume).name
].current
except:
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.current
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)

def get_nominal_tip_overlap_by_configuration(
def get_nominal_tip_overlap_dictionary_by_configuration(
self,
) -> float:
) -> Dict[str, float]:
for config in (
self._config.pick_up_tip_configurations.press_fit,
self._config.pick_up_tip_configurations.cam_action,
Expand All @@ -606,18 +618,22 @@ def get_nominal_tip_overlap_by_configuration(
try:
return config.configuration_by_nozzle_map[approved_map][
pip_types.PipetteTipType(self._liquid_class.max_volume).name
].tip_overlap
except:
default = config.configuration_by_nozzle_map[approved_map].get(
"default"
)
if default is not None:
return default.tip_overlap
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)
].tip_overlap_dictionary
except KeyError:
try:
default = config.configuration_by_nozzle_map[approved_map].get(
"default"
)
if default is not None:
return default.tip_overlap_dictionary
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)
except KeyError:
# No valid key found for the approved nozzle map under this configuration - try the next
continue
raise CommandPreconditionViolated(
message=f"No valid pick-up tip configuration found.",
message="No valid tip overlap dictionary identified.",
)

# Cache max is chosen somewhat arbitrarily. With a float is input we don't
Expand Down
42 changes: 22 additions & 20 deletions api/src/opentrons/hardware_control/instruments/ot3/pipette.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ def __init__(
)
self._flow_acceleration = self._active_tip_settings.default_flow_acceleration

self._tip_overlap = self.get_nominal_tip_overlap_by_configuration()
self._tip_overlap_dictionary = (
self.get_nominal_tip_overlap_dictionary_by_configuration()
)

if use_old_aspiration_functions:
self._pipetting_function_version = PIPETTING_FUNCTION_FALLBACK_VERSION
Expand Down Expand Up @@ -166,8 +168,8 @@ def backlash_distance(self) -> float:
return self._backlash_distance

@property
def tip_overlap(self) -> float:
return self._tip_overlap
def tip_overlap(self) -> Dict[str, float]:
return self._tip_overlap_dictionary

@property
def nozzle_offset(self) -> Point:
Expand Down Expand Up @@ -259,7 +261,9 @@ def reset_state(self) -> None:
)
self._flow_acceleration = self._active_tip_settings.default_flow_acceleration

self._tip_overlap = self.get_nominal_tip_overlap_by_configuration()
self._tip_overlap_dictionary = (
self.get_nominal_tip_overlap_dictionary_by_configuration()
)
self._nozzle_manager = (
nozzle_manager.NozzleConfigurationManager.build_from_config(self._config)
)
Expand Down Expand Up @@ -660,7 +664,9 @@ def set_tip_type(self, tip_type: pip_types.PipetteTipType) -> None:
self._flow_acceleration = self._active_tip_settings.default_flow_acceleration

self._fallback_tip_length = self._active_tip_settings.default_tip_length
self._tip_overlap = self.get_nominal_tip_overlap_by_configuration()
self._tip_overlap_dictionary = (
self.get_nominal_tip_overlap_dictionary_by_configuration()
)
self._working_volume = min(tip_type.value, self.liquid_class.max_volume)

def _get_matching_approved_nozzle_map(self) -> str:
Expand Down Expand Up @@ -720,7 +726,7 @@ def get_pick_up_speed_by_configuration(
return config.configuration_by_nozzle_map[approved_map][
self._active_tip_setting_name.name
].speed
except:
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.speed
Expand All @@ -738,10 +744,8 @@ def get_pick_up_distance_by_configuration(
return config.configuration_by_nozzle_map[approved_map][
self._active_tip_setting_name.name
].distance
except:
default = config.configuration_by_nozzle_map[approved_map].get(
"default"
)
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.distance
raise KeyError(
Expand All @@ -758,17 +762,15 @@ def get_pick_up_current_by_configuration(
return config.configuration_by_nozzle_map[approved_map][
self._active_tip_setting_name.name
].current
except:
default = config.configuration_by_nozzle_map[approved_map].get(
"default"
)
except KeyError:
default = config.configuration_by_nozzle_map[approved_map].get("default")
if default is not None:
return default.current
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)

def get_nominal_tip_overlap_by_configuration(self) -> float:
def get_nominal_tip_overlap_dictionary_by_configuration(self) -> Dict[str, float]:
for config in (
self._config.pick_up_tip_configurations.press_fit,
self._config.pick_up_tip_configurations.cam_action,
Expand All @@ -780,22 +782,22 @@ def get_nominal_tip_overlap_by_configuration(self) -> float:
try:
return config.configuration_by_nozzle_map[approved_map][
self._active_tip_setting_name.name
].tip_overlap
except:
].tip_overlap_dictionary
except KeyError:
try:
default = config.configuration_by_nozzle_map[approved_map].get(
"default"
)
if default is not None:
return default.tip_overlap
return default.tip_overlap_dictionary
raise KeyError(
f"Default tip type configuration values do not exist for Nozzle Map {approved_map}."
)
except:
except KeyError:
# No valid key found for the approved nozzle map under this configuration - try the next
continue
raise CommandPreconditionViolated(
message=f"No valid pick-up tip configuration found.",
message="No valid tip overlap dictionary identified.",
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class LoadedStaticPipetteData:
tip_configuration_lookup_table: Dict[
float, pipette_definition.SupportedTipsDefinition
]
nominal_tip_overlap: float
nominal_tip_overlap: Dict[str, float]
nozzle_map: NozzleMap
back_left_corner_offset: Point
front_right_corner_offset: Point
Expand Down Expand Up @@ -127,7 +127,7 @@ def _get_virtual_pipette_full_config_by_model_string(
pipette_model.pipette_version,
)

def _get_virtual_pipette_static_config_by_model(
def _get_virtual_pipette_static_config_by_model( # noqa: C901
self, pipette_model: pipette_definition.PipetteModelVersionType, pipette_id: str
) -> LoadedStaticPipetteData:
if pipette_id not in self._liquid_class_by_id:
Expand Down Expand Up @@ -157,7 +157,7 @@ def _get_virtual_pipette_static_config_by_model(
)
nozzle_manager = NozzleConfigurationManager.build_from_config(config)

tip_overlap_for_tip_type = None
tip_overlap_dict_for_tip_type = None
for configuration in (
config.pick_up_tip_configurations.press_fit,
config.pick_up_tip_configurations.cam_action,
Expand All @@ -178,23 +178,25 @@ def _get_virtual_pipette_static_config_by_model(

if configuration is not None:
try:
tip_overlap_for_tip_type = (
tip_overlap_dict_for_tip_type = (
configuration.configuration_by_nozzle_map[approved_map][
tip_type.name
].tip_overlap
].tip_overlap_dictionary
)
break
except:
except KeyError:
try:
default = configuration.configuration_by_nozzle_map[
approved_map
].get("default")
if default is not None:
tip_overlap_for_tip_type = default.tip_overlap
tip_overlap_dict_for_tip_type = (
default.tip_overlap_dictionary
)
break
except:
tip_overlap_for_tip_type = None
if tip_overlap_for_tip_type is None:
except KeyError:
tip_overlap_dict_for_tip_type = None
if tip_overlap_dict_for_tip_type is None:
raise ValueError(
"Virtual Static Nozzle Configuration does not have a valid pick up tip configuration."
)
Expand All @@ -220,7 +222,7 @@ def _get_virtual_pipette_static_config_by_model(
default_aspirate=tip_configuration.default_aspirate_flowrate.values_by_api_level,
default_dispense=tip_configuration.default_dispense_flowrate.values_by_api_level,
),
nominal_tip_overlap=tip_overlap_for_tip_type,
nominal_tip_overlap=tip_overlap_dict_for_tip_type,
nozzle_map=nozzle_manager.current_configuration,
back_left_corner_offset=Point(
pip_back_left[0], pip_back_left[1], pip_back_left[2]
Expand Down
5 changes: 4 additions & 1 deletion api/src/opentrons/protocol_engine/state/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,10 @@ def get_nominal_effective_tip_length(
tip overlaps with the pipette nozzle. This does not take calibrated
tip lengths into account.
"""
nominal_overlap = self._pipettes.get_nominal_tip_overlap(pipette_id=pipette_id)
labware_uri = self._labware.get_definition_uri(labware_id)
nominal_overlap = self._pipettes.get_nominal_tip_overlap(
pipette_id=pipette_id, labware_uri=labware_uri
)

return self._labware.get_tip_length(
labware_id=labware_id, overlap=nominal_overlap
Expand Down
12 changes: 8 additions & 4 deletions api/src/opentrons/protocol_engine/state/pipettes.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class StaticPipetteConfig:
tip_configuration_lookup_table: Dict[
float, pipette_definition.SupportedTipsDefinition
]
nominal_tip_overlap: float
nominal_tip_overlap: Dict[str, float]
home_position: float
nozzle_offset_z: float
pipette_bounding_box_offsets: PipetteBoundingBoxOffsets
Expand Down Expand Up @@ -649,10 +649,14 @@ def get_flow_rates(self, pipette_id: str) -> FlowRates:
f"Pipette {pipette_id} not found; unable to get pipette flow rates."
) from e

def get_nominal_tip_overlap(self, pipette_id: str) -> float:
def get_nominal_tip_overlap(self, pipette_id: str, labware_uri: str) -> float:
"""Get the nominal tip overlap for a given labware from config."""
nominal_tip_overlap = self.get_config(pipette_id).nominal_tip_overlap
return nominal_tip_overlap
tip_overlaps_by_uri = self.get_config(pipette_id).nominal_tip_overlap

try:
return tip_overlaps_by_uri[labware_uri]
except KeyError:
return tip_overlaps_by_uri.get("default", 0)

def get_z_axis(self, pipette_id: str) -> MotorAxis:
"""Get the MotorAxis representing this pipette's Z stage."""
Expand Down
5 changes: 4 additions & 1 deletion api/src/opentrons/protocols/api_support/instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ def tip_length_for(
pipette["pipette_id"], tip_rack_definition
).tip_length
except TipLengthCalNotFound:
tip_overlap = pipette["tip_overlap"]
tip_overlap = pipette["tip_overlap"].get(
uri_from_definition(tip_rack_definition),
pipette["tip_overlap"]["default"],
)
tip_length = tip_rack_definition["parameters"]["tipLength"]
return tip_length - tip_overlap

Expand Down

0 comments on commit 350ebd0

Please sign in to comment.