def test_tiprack_list(): labware_name = 'opentrons_96_tiprack_300ul' labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) tiprack_2 = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) assert labware.select_tiprack_from_list( [tiprack], 1) == (tiprack, tiprack['A1']) assert labware.select_tiprack_from_list( [tiprack], 1, tiprack.wells()[1]) == (tiprack, tiprack['B1']) tiprack['C1'].has_tip = False assert labware.select_tiprack_from_list( [tiprack], 1, tiprack.wells()[2]) == (tiprack, tiprack['D1']) tiprack['H12'].has_tip = False tiprack_2['A1'].has_tip = False assert labware.select_tiprack_from_list( [tiprack, tiprack_2], 1, tiprack.wells()[95]) == ( tiprack_2, tiprack_2['B1']) with pytest.raises(labware.OutOfTipsError): labware.select_tiprack_from_list( [tiprack], 1, tiprack.wells()[95])
def test_select_next_tip(): labware_name = 'opentrons_96_tiprack_300ul' labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) well_list = tiprack.wells() next_one = tiprack.next_tip() assert next_one == well_list[0] next_five = tiprack.next_tip(5) assert next_five == well_list[0] next_eight = tiprack.next_tip(8) assert next_eight == well_list[0] next_nine = tiprack.next_tip(9) assert next_nine is None # A1 tip only has been used tiprack.use_tips(well_list[0]) next_one = tiprack.next_tip() assert next_one == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[1] next_eight = tiprack.next_tip(8) assert next_eight == well_list[8] # 2nd column has also been used tiprack.use_tips(well_list[8], num_channels=8) next_one = tiprack.next_tip() assert next_one == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[1] next_eight = tiprack.next_tip(8) assert next_eight == well_list[16] # Bottom 4 tips of 1rd column are also used tiprack.use_tips(well_list[4], num_channels=4) next_one = tiprack.next_tip() assert next_one == well_list[1] next_three = tiprack.next_tip(3) assert next_three == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[16] next_eight = tiprack.next_tip(8) assert next_eight == well_list[16] # you can reuse tips infinitely on api level 2.2 tiprack.use_tips(well_list[0]) tiprack.use_tips(well_list[0]) # you can't on api level 2.1 or previous early_tr = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot'), api_level=APIVersion(2, 1)) early_tr.use_tips(well_list[0]) with pytest.raises(AssertionError): early_tr.use_tips(well_list[0])
def test_tip_tracking_init(): labware_name = 'opentrons_96_tiprack_300ul' labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) assert tiprack.is_tiprack for well in tiprack.wells(): assert well.has_tip labware_name = 'corning_96_wellplate_360ul_flat' labware_def = labware.get_labware_definition(labware_name) lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) assert not lw.is_tiprack for well in lw.wells(): assert not well.has_tip
def test_get_parent_identifier(): labware_name = 'corning_96_wellplate_360ul_flat' labware_def = labware.get_labware_definition(labware_name) lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) # slots have no parent identifier assert labware._get_parent_identifier(lw) == '' # modules do mmg = ModuleGeometry('my magdeck', MagneticModuleModel.MAGNETIC_V1, ModuleType.MAGNETIC, Point(0, 0, 0), 10, 10, Location(Point(1, 2, 3), '3'), APIVersion(2, 4)) lw = labware.Labware(labware_def, mmg.location) assert labware._get_parent_identifier(lw)\ == MagneticModuleModel.MAGNETIC_V1.value
def test_load_calibration(monkeypatch, clear_calibration): calibration_point = None def mock_set_calibration(self, delta): nonlocal calibration_point calibration_point = delta monkeypatch.setattr(labware.Labware, 'set_calibration', mock_set_calibration) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) test_offset = Point(1, 1, 1) test_tip_length = 31.7 labware.save_calibration(test_labware, test_offset) labware.save_tip_length(test_labware, test_tip_length) # Set without saving to show that load will update with previously saved # data test_labware.set_calibration(Point(0, 0, 0)) test_labware.tip_length = 46.8 labware.load_calibration(test_labware) assert calibration_point == test_offset assert test_labware.tip_length == test_tip_length
async def _load_tip_rack_objects(self): """ A function that takes tip rack information and loads them onto the deck. """ second_pip = self._get_pipette_by_rank(PipetteRank.second) for name, lw_data in self._labware_info.items(): parent = self._deck.position_for(lw_data.slot) lw = labware.Labware(lw_data.definition, parent) self._deck[lw_data.slot] = lw for mount in lw_data.forMounts: is_second_mount = second_pip and second_pip.mount == mount pips_share_rack = len(lw_data.forMounts) == 2 well_name = 'A1' if is_second_mount and pips_share_rack: well_name = 'B1' well = lw.wells_by_name()[well_name] position = well.top().point + MOVE_TO_TIP_RACK_SAFETY_BUFFER move = CheckMove(position=position, locationId=uuid4()) if is_second_mount: self._moves.preparingSecondPipette = move else: self._moves.preparingFirstPipette = move
def test_add_index_file(labware_name, index_file_dir): deck = Deck() parent = deck.position_for(1) definition = labware.get_labware_definition(labware_name) lw = labware.Labware(definition, parent) labware_hash = labware._hash_labware_def(lw._definition) labware._add_to_index_offset_file(lw, labware_hash) lw_uri = labware.uri_from_definition(definition) str_parent = labware._get_parent_identifier(lw.parent) slot = '1' if str_parent: mod_dict = {str_parent: f'{slot}-{str_parent}'} else: mod_dict = {} blob = { "id": f'{labware_hash}', "slot": f'{labware_hash}{str_parent}', "module": mod_dict } lw_path = index_file_dir / 'index.json' info = labware._read_file(lw_path) assert info[lw_uri] == blob
def test_air_gap(): m = mock.MagicMock() m.pipette_mock = mock.create_autospec(InstrumentContext) m.mock_set_flow_rate = mock.MagicMock() deck = Location(Point(0, 0, 0), 'deck') well_name = 'A2' some_labware = labware.Labware(minimalLabwareDef2, deck) loaded_labware = {'someLabwareId': some_labware} params = {'labware': 'someLabwareId', 'well': well_name} params = {'pipette': 'somePipetteId', 'volume': 42, 'labware': 'someLabwareId', 'well': well_name, 'offsetFromBottomMm': 12} instruments = {'somePipetteId': m.pipette_mock} loaded_labware = {'someLabwareId': some_labware} with mock.patch( 'opentrons.protocols.execution.execute_json_v3._set_flow_rate', new=m.mock_set_flow_rate): _air_gap(instruments, loaded_labware, params) # NOTE: air_gap `height` arg is mm from well top, # so we expect it to equal offsetFromBottomMm - well depth. assert m.mock_calls == [ mock.call.mock_set_flow_rate(m.pipette_mock, params), mock.call.pipette_mock.move_to( Location(point=Point(x=19, y=28, z=17.0), labware=some_labware[well_name])), mock.call.pipette_mock.air_gap(42, 12 - 40) ]
def test_labware_init(): deck = Location(Point(0, 0, 0), 'deck') fake_labware = labware.Labware(minimalLabwareDef, deck) ordering = [well for col in minimalLabwareDef['ordering'] for well in col] assert fake_labware._ordering == ordering assert fake_labware._well_definition == minimalLabwareDef['wells'] assert fake_labware._offset == Point(x=10, y=10, z=5)
def test_add_index_file(labware_name, labware_offset_tempdir): deck = Deck() parent = deck.position_for(1) definition = labware.get_labware_definition(labware_name) lw = labware.Labware(definition, parent) labware_hash = helpers.hash_labware_def(definition) labware.save_calibration(lw, Point(0, 0, 0)) lw_uri = helpers.uri_from_definition(definition) str_parent = labware._get_parent_identifier(lw) slot = '1' if str_parent: mod_dict = {str_parent: f'{slot}-{str_parent}'} else: mod_dict = {} full_id = f'{labware_hash}{str_parent}' blob = { "uri": f'{lw_uri}', "slot": full_id, "module": mod_dict } lw_path = labware_offset_tempdir / 'index.json' info = file_operators.read_cal_file(lw_path) assert info['data'][full_id] == blob
def test_get_location_with_offset(): deck = Location(Point(0, 0, 0), 'deck') some_labware = labware.Labware(minimalLabwareDef2, deck) loaded_labware = {'someLabwareId': some_labware} params = {'offsetFromBottomMm': 3, 'labware': 'someLabwareId', 'well': 'A2'} result = _get_location_with_offset(loaded_labware, params) assert result == Location(Point(19, 28, 8), some_labware['A2'])
def test_get_well(): deck = Location(Point(0, 0, 0), 'deck') well_name = 'A2' some_labware = labware.Labware(minimalLabwareDef2, deck) loaded_labware = {'someLabwareId': some_labware} params = {'labware': 'someLabwareId', 'well': well_name} result = _get_well(loaded_labware, params) assert result == some_labware[well_name]
def test_uris(): details = ('opentrons', 'opentrons_96_tiprack_300ul', '1') uri = 'opentrons/opentrons_96_tiprack_300ul/1' assert labware.uri_from_details(*details) == uri defn = labware.get_labware_definition(details[1], details[0], details[2]) assert labware.uri_from_definition(defn) == uri lw = labware.Labware(defn, Location(Point(0, 0, 0), 'Test Slot')) assert lw.uri == uri
def test_wells_rebuilt_with_offset(): test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) old_wells = test_labware._wells assert test_labware._offset == Point(10, 10, 5) assert test_labware._calibrated_offset == Point(10, 10, 5) labware.save_calibration(test_labware, Point(2, 2, 2)) new_wells = test_labware._wells assert old_wells[0] != new_wells[0] assert test_labware._offset == Point(10, 10, 5) assert test_labware._calibrated_offset == Point(12, 12, 7)
def test_col_name_accessor(): deck = Location(Point(0, 0, 0), 'deck') fake_labware = labware.Labware(minimalLabwareDef, deck) depth1 = minimalLabwareDef['wells']['A1']['depth'] depth2 = minimalLabwareDef['wells']['A2']['depth'] x = minimalLabwareDef['wells']['A2']['x'] y = minimalLabwareDef['wells']['A2']['y'] offset = fake_labware._offset a1 = Point(x=offset[0], y=offset[1], z=offset[2] + depth1) a2 = Point(x=offset[0] + x, y=offset[1] + y, z=offset[2] + depth2) assert fake_labware.columns_by_name()['1'][0]._position == a1 assert fake_labware.columns_by_name()['2'][0]._position == a2
def test_save_tip_length(monkeypatch, clear_calibration): assert not os.path.exists(path(MOCK_HASH)) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) calibrated_length = 22.0 labware.save_tip_length(test_labware, calibrated_length) assert os.path.exists(path(MOCK_HASH)) with open(path(MOCK_HASH)) as calibration_file: data = json.load(calibration_file) assert data['tipLength']['length'] == calibrated_length
def set_up_index_file_temporary_directory(server_temp_directory): delete.clear_calibrations() deck = Deck() labware_list = [ 'nest_96_wellplate_2ml_deep', 'corning_384_wellplate_112ul_flat', 'geb_96_tiprack_1000ul', 'nest_12_reservoir_15ml', 'opentrons_96_tiprack_10ul' ] for idx, name in enumerate(labware_list): parent = deck.position_for(idx + 1) definition = labware.get_labware_definition(name) lw = labware.Labware(definition, parent) labware.save_calibration(lw, Point(0, 0, 0))
def test_get_location_with_offset_fixed_trash(): deck = Location(Point(0, 0, 0), 'deck') trash_labware_def = deepcopy(minimalLabwareDef2) trash_labware_def['parameters']['quirks'] = ["fixedTrash"] trash_labware = labware.Labware(trash_labware_def, deck) loaded_labware = {'someLabwareId': trash_labware} params = {'offsetFromBottomMm': 3, 'labware': 'someLabwareId', 'well': 'A1'} result = _get_location_with_offset(loaded_labware, params) assert result == Location(Point(10, 28, 45), trash_labware['A1'])
def test_load_tip_length_calibration_data(monkeypatch, clear_tlc_calibration): assert not os.path.exists(tlc_path(PIPETTE_ID)) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) tip_length = 22.0 test_data = labware.create_tip_length_data(test_labware, tip_length) labware.save_tip_length_calibration(PIPETTE_ID, test_data) result = labware.load_tip_length_calibration(PIPETTE_ID, test_labware) assert result == test_data[MOCK_HASH]
def set_up_index_file(labware_offset_tempdir): deck = Deck() labware_list = [ 'nest_96_wellplate_2ml_deep', 'corning_384_wellplate_112ul_flat', 'geb_96_tiprack_1000ul', 'nest_12_reservoir_15ml'] for idx, name in enumerate(labware_list): parent = deck.position_for(idx+1) definition = labware.get_labware_definition(name) lw = labware.Labware(definition, parent) labware.save_calibration(lw, Point(0, 0, 0)) return labware_list
def test_row_name_accessor(): deck = Location(Point(0, 0, 0), 'deck') fake_labware = labware.Labware(minimalLabwareDef2, deck) depth1 = minimalLabwareDef2['wells']['A1']['depth'] x1 = minimalLabwareDef2['wells']['A1']['x'] y1 = minimalLabwareDef2['wells']['A1']['y'] depth2 = minimalLabwareDef2['wells']['B2']['depth'] x2 = minimalLabwareDef2['wells']['B2']['x'] y2 = minimalLabwareDef2['wells']['B2']['y'] offset = fake_labware._offset a1 = Point(x=offset[0] + x1, y=offset[1] + y1, z=offset[2] + depth1) b2 = Point(x=offset[0] + x2, y=offset[1] + y2, z=offset[2] + depth2) assert fake_labware.rows_by_name()['A'][0]._position == a1 assert fake_labware.rows_by_name()['B'][1]._position == b2
def test_well_parent(): labware_name = 'corning_96_wellplate_360ul_flat' labware_def = labware.get_labware_definition(labware_name) lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) parent = Location(Point(7, 8, 9), lw) well_name = 'circular_well_json' has_tip = True well = labware.Well(test_data[well_name], parent, well_name, has_tip) assert well.parent is lw assert well.top().labware is well assert well.top().labware.parent is lw assert well.bottom().labware is well assert well.bottom().labware.parent is lw assert well.center().labware is well assert well.center().labware.parent is lw
def test_schema_shape(monkeypatch, clear_calibration): def fake_time(): return 1 monkeypatch.setattr(time, 'time', fake_time) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) monkeypatch.setattr(labware, '_hash_labware_def', mock_hash_labware) labware.save_calibration(test_labware, Point(1, 1, 1)) expected = {"default": {"offset": [1, 1, 1], "lastModified": 1}} with open(path(MOCK_HASH)) as f: result = json.load(f) assert result == expected
def test_select_next_tip(): labware_name = 'opentrons_96_tiprack_300ul' labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) well_list = tiprack.wells() next_one = tiprack.next_tip() assert next_one == well_list[0] next_five = tiprack.next_tip(5) assert next_five == well_list[0] next_eight = tiprack.next_tip(8) assert next_eight == well_list[0] next_nine = tiprack.next_tip(9) assert next_nine is None # A1 tip only has been used tiprack.use_tips(well_list[0]) next_one = tiprack.next_tip() assert next_one == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[1] next_eight = tiprack.next_tip(8) assert next_eight == well_list[8] # 2nd column has also been used tiprack.use_tips(well_list[8], num_channels=8) next_one = tiprack.next_tip() assert next_one == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[1] next_eight = tiprack.next_tip(8) assert next_eight == well_list[16] # Bottom 4 tips of 1rd column are also used tiprack.use_tips(well_list[4], num_channels=4) next_one = tiprack.next_tip() assert next_one == well_list[1] next_three = tiprack.next_tip(3) assert next_three == well_list[1] next_five = tiprack.next_tip(5) assert next_five == well_list[16] next_eight = tiprack.next_tip(8) assert next_eight == well_list[16]
def test_previous_tip(): labware_name = 'opentrons_96_tiprack_300ul' labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) # If all wells are used, we can't get a previous tip assert tiprack.previous_tip() is None # If one well is empty, wherever it is, we can get a slot tiprack.wells()[5].has_tip = False assert tiprack.previous_tip() is tiprack.wells()[5] # But not if we ask for more slots than are available assert tiprack.previous_tip(2) is None tiprack.wells()[7].has_tip = False # And those available wells have to be contiguous assert tiprack.previous_tip(2) is None # But if they are, we're good tiprack.wells()[6].has_tip = False assert tiprack.previous_tip(3) is tiprack.wells()[5]
def test_back_compat(): labware_name = 'corning_96_wellplate_360ul_flat' labware_def = labware.get_labware_definition(labware_name) lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) # Note that this test uses the display name of wells to test for equality, # because dimensional parameters could be subject to modification through # calibration, whereas here we are testing for "identity" in a way that is # related to the combination of well name, labware name, and slot name well_a1_name = repr(lw.wells_by_name()['A1']) well_b2_name = repr(lw.wells_by_name()['B2']) well_c3_name = repr(lw.wells_by_name()['C3']) w2 = lw.well(0) assert repr(w2) == well_a1_name w3 = lw.well('A1') assert repr(w3) == well_a1_name w4 = lw.wells('B2') assert repr(w4[0]) == well_b2_name w5 = lw.wells(9, 21, 25, 27) assert len(w5) == 4 assert repr(w5[0]) == well_b2_name w6 = lw.wells('A1', 'B2', 'C3') assert all([ repr(well[0]) == well[1] for well in zip(w6, [well_a1_name, well_b2_name, well_c3_name]) ]) w7 = lw.rows('A') assert len(w7) == 1 assert repr(w7[0][0]) == well_a1_name w8 = lw.rows('A', 'C') assert len(w8) == 2 assert repr(w8[0][0]) == well_a1_name assert repr(w8[1][2]) == well_c3_name w11 = lw.columns('2', '3', '6') assert len(w11) == 3 assert repr(w11[1][2]) == well_c3_name
def test_load_calibration(monkeypatch, clear_calibration): monkeypatch.setattr(helpers, 'hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) test_offset = Point(1, 1, 1) labware.save_calibration(test_labware, test_offset) # Set without saving to show that load will update with previously saved # data test_labware.set_calibration(Point(0, 0, 0)) test_labware.tip_length = 46.8 lookup_path = labware._get_labware_path(test_labware) calibration_point =\ get.get_labware_calibration(lookup_path, test_labware._definition) assert calibration_point == test_offset
async def _load_labware_objects(self, **kwargs): """ A function that takes tiprack information and loads them onto the deck. """ full_dict = {} for name, data in self._labware_info.items(): parent = self._deck.position_for(data.slot) lw = labware.Labware(data.definition, parent) self._deck[data.slot] = lw build_dict = {} for id in data.forPipettes: mount = self._get_mount(id) pip = self.get_pipette(mount) well_name = 'H1' if pip['channels'] == 8 else 'A1' well = lw.wells_by_name()[well_name] build_dict[id] = PreparingPipetteMoveOffset( offset=Point(0, 0, 10), well=well ) full_dict[data.id] = build_dict self._moves.preparingPipette = full_dict
def test_save_labware_calibration(monkeypatch, clear_calibration): # Test the save calibration file assert not os.path.exists(path(MOCK_HASH)) calibration_point = None def mock_set_calibration(self, delta): nonlocal calibration_point calibration_point = delta monkeypatch.setattr(labware.Labware, 'set_calibration', mock_set_calibration) monkeypatch.setattr(helpers, 'hash_labware_def', mock_hash_labware) test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) labware.save_calibration(test_labware, Point(1, 1, 1)) assert os.path.exists(path(MOCK_HASH)) assert calibration_point == Point(1, 1, 1)
def test_schema_shape(monkeypatch, clear_calibration): fake_time = utc_now() time_string = fake_time.isoformat() from_iso = datetime.datetime.fromisoformat(time_string) class fake_datetime: @classmethod def fromisoformat(cls, obj): return from_iso @classmethod def isoformat(cls): return time_string mock = Mock(spec=fake_datetime) mock.__class__ = datetime.datetime test_labware = labware.Labware(minimalLabwareDef, Location(Point(0, 0, 0), 'deck')) monkeypatch.setattr( helpers, 'hash_labware_def', mock_hash_labware ) expected = {"default": {"offset": [1, 1, 1], "lastModified": fake_time}} def fake_helper_data(path, delta): return expected monkeypatch.setattr( modify, '_helper_offset_data_format', fake_helper_data ) labware.save_calibration(test_labware, Point(1, 1, 1)) with open(path(MOCK_HASH)) as f: result = json.load(f, cls=ed.DateTimeDecoder) assert result == expected