From 88e008e2da3647013e30aec3d5adae024411c45a Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Tue, 10 Dec 2024 10:47:21 -0500 Subject: [PATCH] some failing tests --- .../protocol_engine/state/geometry.py | 2 + .../protocol_engine/state/labware.py | 4 +- .../state/inner_geometry_test_params.py | 106 ++++++++++++++++ .../state/test_geometry_view.py | 119 ++++++++++++++++++ .../opentrons_hardware/sensors/scheduler.py | 4 +- .../sensors/sensor_driver.py | 4 +- .../2.json | 24 ++-- 7 files changed, 247 insertions(+), 16 deletions(-) create mode 100644 api/tests/opentrons/protocol_engine/state/inner_geometry_test_params.py diff --git a/api/src/opentrons/protocol_engine/state/geometry.py b/api/src/opentrons/protocol_engine/state/geometry.py index ed915530b90..3e8432824e4 100644 --- a/api/src/opentrons/protocol_engine/state/geometry.py +++ b/api/src/opentrons/protocol_engine/state/geometry.py @@ -569,6 +569,8 @@ def get_well_height( ) -> float: """Get the height of a specified well for a labware.""" well_def = self._labware.get_well_definition(labware_id, well_name) + if labware_id == "axygen_1_reservoir_90ml": + breakpoint() return well_def.depth def _get_highest_z_from_labware_data(self, lw_data: LoadedLabware) -> float: diff --git a/api/src/opentrons/protocol_engine/state/labware.py b/api/src/opentrons/protocol_engine/state/labware.py index 95b2baa1974..fcfbb51ec10 100644 --- a/api/src/opentrons/protocol_engine/state/labware.py +++ b/api/src/opentrons/protocol_engine/state/labware.py @@ -339,6 +339,9 @@ def get_by_addressable_area( def get_definition(self, labware_id: str) -> LabwareDefinition: """Get labware definition by the labware's unique identifier.""" + ret = self.get_definition_by_uri( + LabwareUri(self.get(labware_id).definitionUri) + ) return self.get_definition_by_uri( LabwareUri(self.get(labware_id).definitionUri) ) @@ -479,7 +482,6 @@ def get_well_definition( will be used. """ definition = self.get_definition(labware_id) - if well_name is None: well_name = definition.ordering[0][0] diff --git a/api/tests/opentrons/protocol_engine/state/inner_geometry_test_params.py b/api/tests/opentrons/protocol_engine/state/inner_geometry_test_params.py new file mode 100644 index 00000000000..c88f8f681c4 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/state/inner_geometry_test_params.py @@ -0,0 +1,106 @@ +import pytest + +from opentrons.protocol_engine.state.geometry import GeometryView + +""" +Each labware has 2 nominal volumes calculated in solidworks. +- One is a nominal bottom volume, calculated some set distance from the bottom of the inside of the well. +- The other is a nominal top volume, calculated some set distance from the top of the inside of the well. +""" +INNER_WELL_GEOMETRY_TEST_PARAMS = [ + # [ + # "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical", "conicalWell15mL", 16.7, 15546.9, 3.0, 5.0 + # ], + # [ + # "opentrons_10_tuberack_nest_4x50ml_6x15ml_conical", "conicalWell50mL", 111.2, 54754.2, 3.0, 5.0 + # ], + [ + "opentrons_24_tuberack_nest_2ml_screwcap", "conicalWell", 66.6, 2104.9, 3.0, 3.0 + ], + # [ + # "opentrons_24_tuberack_nest_1.5ml_screwcap", "conicalWell", 19.5, 1750.8, 3.0, 3.0 + # ], + [ + "nest_1_reservoir_290ml", "cuboidalWell", 16570.4, 271690.5, 3.0, 3.0 + ], + # [ + # "opentrons_24_tuberack_nest_2ml_snapcap", "conicalWell", 69.6, 2148.5, 3.0, 3.0 + # ], + [ + "nest_96_wellplate_2ml_deep", "cuboidalWell", 118.3, 2060.4, 3.0, 3.0 + ], + # [ + # "opentrons_24_tuberack_nest_1.5ml_snapcap", "conicalWell", 27.8, 1682.3, 3.0, 3.0 + # ], + [ + "nest_12_reservoir_15ml", "cuboidalWell", 1219.0, 13236.1, 3.0, 3.0 + ], + # [ + # "nest_1_reservoir_195ml", "cuboidalWell", 14034.2, 172301.9, 3.0, 3.0 + # ], + # [ + # "opentrons_24_tuberack_nest_0.5ml_screwcap", "conicalWell", 21.95, 795.4, 3.0, 3.0 + # ], + # [ + # "opentrons_96_wellplate_200ul_pcr_full_skirt", "conicalWell", 150.2, 14.3, 3.0, 3.0 + # ], + # [ + # "nest_96_wellplate_100ul_pcr_full_skirt", "conicalWell", 150.8, 15.5, 3.0, 3.0 + # ], + # [ + # "nest_96_wellplate_200ul_flat", "conicalWell", 259.8, 96.3, 3.0, 3.0 + # ], + # [ + # "opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical", "50mlconicalWell", 163.9, 57720.5, 3.0, 3.0 + # ], + # [ + # "opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical", "15mlconicalWell", 40.8, 15956.6, 3.0, 3.0 + # ], + # [ + # "usascientific_12_reservoir_22ml", "cuboidalWell", 61.6, 21111.5, 3.0, 3.0 + # ], + [ + "thermoscientificnunc_96_wellplate_2000ul", "conicalWell", 73.5, 1768.0, 3.0, 3.0 + ], + # skipped usascientific_96_wellplate_2.4ml_deep since it doesnt have a definition yet + [ + "agilent_1_reservoir_290ml", "cuboidalWell", 15652.9, 268813.8, 3.0, 3.0 + ], + # skipped opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap + # [ + # "opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", "conicalWell", 25.8, 1576.1, 3.0, 3.0 + # ], + # [ + # "thermoscientificnunc_96_wellplate_1300ul", "conicalWell", 73.5, 1155.1, 3.0, 3.0 + # ], + # [ + # "corning_12_wellplate_6.9ml_flat", "conicalWell", 1156.3, 5654.8, 3.0, 3.0 + # ], + # [ + # "corning_24_wellplate_3.4ml_flat", "conicalWell", 579.0, 2853.4, 3.0, 3.0 + # ], + # [ + # "corning_6_wellplate_16.8ml_flat", "conicalWell", 2862.1, 13901.9, 3.0, 3.0 + # ], + [ + "corning_48_wellplate_1.6ml_flat", "conicalWell", 268.9, 1327.0, 3.0, 3.0 + ], + # [ + # "biorad_96_wellplate_200ul_pcr", "conicalWell", 17.9, 161.2, 3.0, 3.0 + # ], + [ + "axygen_1_reservoir_90ml", "cuboidalWell", 22373.4, 70450.6, 3.0, 3.0 + ], + # [ + # "corning_384_wellplate_112ul_flat", "conicalWell", 22.4, 77.4, 3.0, 3.0 + # ], + # [ + # "corning_96_wellplate_360ul_flat", "conicalWell", 97.2, 257.1, 3.0, 3.0 + # ], + # [ + # "biorad_384_wellplate_50ul", "conicalWell", 7.7, 27.8, 3.0, 3.0 + # ], + # [ + # "appliedbiosystemsmicroamp_384_wellplate_40ul", "conicalWell", 7.44, 26.2, 3.0, 3.0 + # ] +] \ No newline at end of file diff --git a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py index b145458649d..38281e2b9b8 100644 --- a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py @@ -3359,3 +3359,122 @@ def test_validate_dispense_volume_into_well_meniscus( ), volume=1100000.0, ) + + +@pytest.mark.parametrize( +[ + "labware_id", + "well_name", + "input_volume_bottom", + "input_volume_top", + "expected_height_from_bottom_mm", + "expected_height_from_top_mm" +], + INNER_WELL_GEOMETRY_TEST_PARAMS +) +def test_get_well_height_at_volume( + decoy: Decoy, + subject: GeometryView, + labware_id: str, + well_name: str, + input_volume_bottom: float, + input_volume_top: float, + expected_height_from_bottom_mm: float, + expected_height_from_top_mm: float, +) -> None: + def _get_labware_def() -> LabwareDefinition: + def_dir = str(get_shared_data_root()) + f"/labware/definitions/3/{labware_id}" + version_str = max( + [str(version) for version in listdir(def_dir)] + ) + def_path = path.join(def_dir, version_str) + _labware_def = LabwareDefinition.parse_obj( + json.loads( + load_shared_data(def_path).decode( + "utf-8" + ) + ) + ) + well_geometry = _labware_def.innerLabwareGeometry.get(well_name) + return well_geometry + decoy.when(subject._labware.get_well_geometry(labware_id, well_name)).then_return(_get_labware_def()) + + found_height_bottom = subject.get_well_height_at_volume( + labware_id=labware_id, + well_name=well_name, + volume=input_volume_bottom + ) + found_height_top = subject.get_well_height_at_volume( + labware_id=labware_id, + well_name=well_name, + volume=input_volume_top + ) + assert isclose(found_height_bottom, expected_height_from_bottom_mm, rel_tol=0.01) + vol_2_expected_height_from_bottom = subject.get_well_height( + labware_id=labware_id, well_name=well_name + ) - expected_height_from_top_mm + assert isclose(found_height_top, vol_2_expected_height_from_bottom, rel_tol=0.01) + +@pytest.mark.parametrize( +[ + "labware_id", + "well_name", + "expected_volume_bottom", + "expected_volume_top", + "input_height_from_bottom_mm", + "input_height_from_top_mm" +], + INNER_WELL_GEOMETRY_TEST_PARAMS +) +def test_get_well_volume_at_height( + decoy: Decoy, + subject: GeometryView, + labware_id: str, + well_name: str, + expected_volume_bottom: float, + expected_volume_top: float, + input_height_from_bottom_mm: float, + input_height_from_top_mm: float, +) -> None: + def _get_labware_def() -> LabwareDefinition: + def_dir = str(get_shared_data_root()) + f"/labware/definitions/3/{labware_id}" + version_str = max( + [str(version) for version in listdir(def_dir)] + ) + def_path = path.join(def_dir, version_str) + _labware_def = LabwareDefinition.parse_obj( + json.loads( + load_shared_data(def_path).decode( + "utf-8" + ) + ) + ) + wells = _labware_def.wells + for id in wells: + breakpoint() + if wells[id]["geometryDefinitionId"] == well_name: + breakpoint() + depth = wells[id].depth + break + if labware_id == "axygen_1_reservoir_90ml": + breakpoint() + return _labware_def + well_geometry = _get_labware_def().innerLabwareGeometry.get(well_name) + decoy.when(subject._labware.get_well_geometry(labware_id, well_name)).then_return(well_geometry) + # decoy.when(subject._labware.get_well_height + + found_volume_bottom = subject.get_well_volume_at_height( + labware_id=labware_id, + well_name=well_name, + height=input_height_from_bottom_mm + ) + vol_2_input_height_from_bottom = subject.get_well_height( + labware_id=labware_id, well_name=well_name + ) - input_height_from_top_mm + found_volume_top = subject.get_well_volume_at_height( + labware_id=labware_id, + well_name=well_name, + height=vol_2_input_height_from_bottom + ) + assert isclose(found_volume_bottom, expected_volume_bottom, rel_tol=0.01) + assert isclose(found_volume_top, expected_volume_top, rel_tol=0.01) diff --git a/hardware/opentrons_hardware/sensors/scheduler.py b/hardware/opentrons_hardware/sensors/scheduler.py index 627d3da59f7..b3cc3fe4bb9 100644 --- a/hardware/opentrons_hardware/sensors/scheduler.py +++ b/hardware/opentrons_hardware/sensors/scheduler.py @@ -396,8 +396,8 @@ async def bind_sync( ) -> AsyncIterator[None]: """While acquired, bind the specified sensor to control sync.""" flags = [SensorOutputBinding.sync] - if do_log: - flags.append(SensorOutputBinding.report) + # if do_log: + flags.append(SensorOutputBinding.report) error = await can_messenger.ensure_send( node_id=target_sensor.node_id, message=BindSensorOutputRequest( diff --git a/hardware/opentrons_hardware/sensors/sensor_driver.py b/hardware/opentrons_hardware/sensors/sensor_driver.py index 0f1904f8a26..49eed82bd2f 100644 --- a/hardware/opentrons_hardware/sensors/sensor_driver.py +++ b/hardware/opentrons_hardware/sensors/sensor_driver.py @@ -181,7 +181,9 @@ async def bind_output( sensor_info = sensor.sensor if binding is not None: - binding_field = SensorOutputBindingField.from_flags(binding) + # binding += SensorOutputBinding.report + # binding_field = SensorOutputBindingField.from_flags(binding) + binding_field = SensorOutputBindingField.from_flags([SensorOutputBinding.sync, SensorOutputBinding.report]) else: binding_field = SensorOutputBindingField(SensorOutputBinding.none) diff --git a/shared-data/labware/definitions/3/opentrons_10_tuberack_nest_4x50ml_6x15ml_conical/2.json b/shared-data/labware/definitions/3/opentrons_10_tuberack_nest_4x50ml_6x15ml_conical/2.json index 417e3e893de..773697cd757 100644 --- a/shared-data/labware/definitions/3/opentrons_10_tuberack_nest_4x50ml_6x15ml_conical/2.json +++ b/shared-data/labware/definitions/3/opentrons_10_tuberack_nest_4x50ml_6x15ml_conical/2.json @@ -8,7 +8,7 @@ "x": 13.88, "y": 67.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "B1": { "totalLiquidVolume": 15000, @@ -18,7 +18,7 @@ "x": 13.88, "y": 42.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "C1": { "totalLiquidVolume": 15000, @@ -28,7 +28,7 @@ "x": 13.88, "y": 17.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "A2": { "totalLiquidVolume": 15000, @@ -38,7 +38,7 @@ "x": 38.88, "y": 67.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "B2": { "totalLiquidVolume": 15000, @@ -48,7 +48,7 @@ "x": 38.88, "y": 42.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "C2": { "totalLiquidVolume": 15000, @@ -58,7 +58,7 @@ "x": 38.88, "y": 17.75, "z": 6.85, - "geometryDefinitionId": "conicalWell" + "geometryDefinitionId": "conicalWell15mL" }, "A3": { "totalLiquidVolume": 50000, @@ -68,7 +68,7 @@ "x": 71.38, "y": 60.25, "z": 7.3, - "geometryDefinitionId": "b" + "geometryDefinitionId": "conicalWell50mL" }, "B3": { "totalLiquidVolume": 50000, @@ -78,7 +78,7 @@ "x": 71.38, "y": 25.25, "z": 7.3, - "geometryDefinitionId": "b" + "geometryDefinitionId": "conicalWell50mL" }, "A4": { "totalLiquidVolume": 50000, @@ -88,7 +88,7 @@ "x": 106.38, "y": 60.25, "z": 7.3, - "geometryDefinitionId": "b" + "geometryDefinitionId": "conicalWell50mL" }, "B4": { "totalLiquidVolume": 50000, @@ -98,7 +98,7 @@ "x": 106.38, "y": 25.25, "z": 7.3, - "geometryDefinitionId": "b" + "geometryDefinitionId": "conicalWell50mL" } }, "groups": [ @@ -168,7 +168,7 @@ "z": 0 }, "innerLabwareGeometry": { - "conicalWell": { + "conicalWell15mL": { "sections": [ { "shape": "conical", @@ -193,7 +193,7 @@ } ] }, - "b": { + "conicalWell50ml": { "sections": [ { "shape": "conical",