def test_magdeck_labware_props(loop): ctx = papi.ProtocolContext(loop) # TODO Ian 2019-05-29 load fixtures, not real defs labware_name = 'biorad_96_wellplate_200ul_pcr' labware_def = json.loads( load_shared_data(f'labware/definitions/2/{labware_name}/1.json')) ctx._hw_manager.hardware._backend._attached_modules = [('mod0', 'magdeck')] mod = ctx.load_module('magdeck', 1) assert mod.labware is None mod.load_labware(labware_name) mod.engage() lw_offset = labware_def['parameters']['magneticModuleEngageHeight'] assert mod._module._driver.plate_height == lw_offset mod.disengage() mod.engage(offset=2) assert mod._module._driver.plate_height == lw_offset + 2 mod.disengage() mod.engage(height=3) assert mod._module._driver.plate_height == 3 mod._geometry.reset_labware() labware_name = 'corning_96_wellplate_360ul_flat' mod.load_labware(labware_name) with pytest.raises(ValueError): mod.engage() with pytest.raises(ValueError): mod.engage(offset=1) mod.engage(height=2) assert mod._module._driver.plate_height == 2 mod.engage(height_from_base=2) assert mod._module._driver.plate_height == 2 + OFFSET_TO_LABWARE_BOTTOM
def _load_v2_module_def(module_model: ModuleModel) -> Dict[str, Any]: try: return json.loads( load_shared_data( f'module/definitions/2/{module_model.value}.json')) except OSError: raise NoSuchModuleError( f'Could not find the module {module_model.value}.', module_model)
def _load_v1_module_def(module_model: ModuleModel) -> Dict[str, Any]: v1names = { MagneticModuleModel.MAGNETIC_V1: 'magdeck', TemperatureModuleModel.TEMPERATURE_V1: 'tempdeck', ThermocyclerModuleModel.THERMOCYCLER_V1: 'thermocycler' } try: name = v1names[module_model] except KeyError: raise NoSuchModuleError(f'Could not find module {module_model.value}', module_model) return json.loads(load_shared_data('module/definitions/1.json'))[name]
def validate_json(protocol_json: Dict[Any, Any]) -> int: """ Validates a json protocol and returns its schema version """ # Check if this is actually a labware labware_schema_v2 = json.loads(load_shared_data( 'labware/schemas/2.json').decode('utf-8')) try: jsonschema.validate(protocol_json, labware_schema_v2) except jsonschema.ValidationError: pass else: MODULE_LOG.error("labware uploaded instead of protocol") raise RuntimeError( 'The file you are trying to open is a JSON labware definition, ' 'and therefore can not be opened here. Please try ' 'uploading a JSON protocol file instead.') # this is now either a protocol or something corrupt version_num = _get_protocol_schema_version(protocol_json) if version_num <= 2: raise RuntimeError( f'JSON protocol version {version_num} is ' 'deprecated. Please upload your protocol into Protocol ' 'Designer and save it to migrate the protocol to a later ' 'version. This error might mean a labware ' 'definition was specified instead of a protocol.') if version_num > 4: raise RuntimeError( f'The protocol you are trying to open is a JSONv{version_num} ' 'protocol and is not supported by your current robot server ' 'version. Please update your OT-2 App and robot server to the ' 'latest version and try again.' ) protocol_schema = _get_schema_for_protocol(version_num) # instruct schema how to resolve all $ref's used in protocol schemas resolver = jsonschema.RefResolver( protocol_schema.get('$id', ''), protocol_schema, store={ "opentronsLabwareSchemaV2": labware_schema_v2 }) # do the validation try: jsonschema.validate(protocol_json, protocol_schema, resolver=resolver) except jsonschema.ValidationError: MODULE_LOG.exception("JSON protocol validation failed") raise RuntimeError( 'This may be a corrupted file or a JSON file that is not an ' 'Opentrons JSON protocol.') else: return version_num
def _get_schema_for_protocol(version_num: int) -> Dict[Any, Any]: """ Retrieve the json schema for a protocol schema version """ if version_num > 3: raise RuntimeError(f'JSON Protocol version {version_num} is not yet ' + 'supported in this version of the API') try: schema = load_shared_data(f'protocol/schemas/{version_num}.json') except FileNotFoundError: schema = None # type: ignore if not schema: raise RuntimeError( 'JSON Protocol schema "{}" does not exist'.format(version_num)) return json.loads(schema.decode('utf-8'))
def __init__(self): super().__init__() row_offset = 90.5 col_offset = 132.5 for idx in range(1, 13): self.data[idx] = None self._positions = { idx + 1: types.Point((idx % 3) * col_offset, idx // 3 * row_offset, 0) for idx in range(12) } self._highest_z = 0.0 # TODO: support deck loadName as a param def_path = 'deck/definitions/2/ot2_standard.json' self._definition = json.loads(load_shared_data(def_path))
def _get_schema_for_protocol(version_num: int) -> Dict[Any, Any]: """ Retrieve the json schema for a protocol schema version """ # TODO(IL, 2020/03/05): use $otSharedSchema, but maybe wait until # deprecating v1/v2 JSON protocols? if version_num > 4: raise RuntimeError(f'JSON Protocol version {version_num} is not yet ' + 'supported in this version of the API') try: schema = load_shared_data(f'protocol/schemas/{version_num}.json') except FileNotFoundError: schema = None # type: ignore if not schema: raise RuntimeError( 'JSON Protocol schema "{}" does not exist'.format(version_num)) return json.loads(schema.decode('utf-8'))
def test_module_load_v1(v1_module_name): module_defs = json.loads(load_shared_data('module/definitions/1.json')) model = module_geometry.resolve_module_model(v1_module_name) mod = module_geometry.load_module(model, Location(Point(0, 0, 0), 'test')) mod_def = module_defs[v1_module_name] offset = Point(mod_def['labwareOffset']['x'], mod_def['labwareOffset']['y'], mod_def['labwareOffset']['z']) high_z = mod_def['dimensions']['bareOverallHeight'] assert mod.highest_z == high_z assert mod.location.point == offset mod = module_geometry.load_module(model, Location(Point(1, 2, 3), 'test')) assert mod.highest_z == high_z + 3 assert mod.location.point == (offset + Point(1, 2, 3)) mod2 = module_geometry.load_module_from_definition( module_defs[v1_module_name], Location(Point(3, 2, 1), 'test2')) assert mod2.highest_z == high_z + 1 assert mod2.location.point == (offset + Point(3, 2, 1))
def test_module_load(): module_names = ['tempdeck', 'magdeck'] module_defs = json.loads(load_shared_data('module/definitions/1.json')) for name in module_names: mod = labware.load_module(name, Location(Point(0, 0, 0), 'test')) mod_def = module_defs[name] offset = Point(mod_def['labwareOffset']['x'], mod_def['labwareOffset']['y'], mod_def['labwareOffset']['z']) high_z = mod_def['dimensions']['bareOverallHeight'] assert mod.highest_z == high_z assert mod.location.point == offset mod = labware.load_module(name, Location(Point(1, 2, 3), 'test')) assert mod.highest_z == high_z + 3 assert mod.location.point == (offset + Point(1, 2, 3)) mod2 = labware.load_module_from_definition( mod_def, Location(Point(3, 2, 1), 'test2')) assert mod2.highest_z == high_z + 1 assert mod2.location.point == (offset + Point(3, 2, 1))
def load_module_from_definition( definition: Dict[str, Any], parent: Location, api_level: APIVersion = None, configuration: GenericConfiguration = ThermocyclerConfiguration.FULL ) -> ModuleGeometry: """ Return a :py:class:`ModuleGeometry` object from a specified definition matching the v1 module definition schema :param definition: A dict representing the full module definition adhering to the v1 module schema :param parent: A :py:class:`.Location` representing the location where the front and left most point of the outside of the module is (often the front-left corner of a slot on the deck). :param APIVersion api_level: the API version to set for the loaded :py:class:`ModuleGeometry` instance. The :py:class:`ModuleGeometry` will conform to this level. If not specified, defaults to :py:attr:`.MAX_SUPPORTED_VERSION`. """ api_level = api_level or MAX_SUPPORTED_VERSION schema = definition.get("$otSharedSchema") if not schema: # v1 definitions don't have schema versions return _load_from_v1(definition, parent, api_level) if schema == 'module/schemas/2': schema_doc = json.loads(load_shared_data("module/schemas/2.json")) try: jsonschema.validate(definition, schema_doc) except jsonschema.ValidationError: log.exception("Failed to validate module def schema") raise RuntimeError('The specified module definition is not valid.') return _load_from_v2(definition, parent, api_level, configuration) elif isinstance(schema, str): maybe_schema = re.match('^module/schemas/([0-9]+)$', schema) if maybe_schema: raise RuntimeError( f"Module definitions of schema version {maybe_schema.group(1)}" " are not supported in this robot software release.") log.error(f"Bad module definition (schema specifier {schema})") raise RuntimeError('The specified module definition is not valid.')
def test_module_load_labware(loop): ctx = papi.ProtocolContext(loop) labware_name = 'corning_96_wellplate_360ul_flat' # TODO Ian 2019-05-29 load fixtures, not real defs labware_def = json.loads( load_shared_data(f'labware/definitions/2/{labware_name}/1.json')) ctx._hw_manager.hardware._backend._attached_modules = [ ('mod0', 'tempdeck')] mod = ctx.load_module('Temperature Module', 1) assert mod.labware is None lw = mod.load_labware(labware_name) lw_offset = Point(labware_def['cornerOffsetFromSlot']['x'], labware_def['cornerOffsetFromSlot']['y'], labware_def['cornerOffsetFromSlot']['z']) assert lw._offset == lw_offset + mod._geometry.location.point assert lw.name == labware_name # Test load with old name mod2 = ctx.load_module('tempdeck', 2) lw2 = mod2.load_labware(labware_name) assert lw2._offset == lw_offset + mod2._geometry.location.point
def verify_definition(contents: Union[AnyStr, LabwareDefinition])\ -> LabwareDefinition: """ Verify that an input string is a labware definition and return it. If the definition is invalid, an exception is raised; otherwise parse the json and return the valid definition. :raises json.JsonDecodeError: If the definition is not valid json :raises jsonschema.ValidationError: If the definition is not valid. :returns: The parsed definition """ schema_body = load_shared_data('labware/schemas/2.json').decode('utf-8') labware_schema_v2 = json.loads(schema_body) if isinstance(contents, dict): to_return = contents jsonschema.validate(to_return, labware_schema_v2) else: to_return = json.loads(contents) jsonschema.validate(to_return, labware_schema_v2) return to_return
def test_magdeck_gen1_labware_props(loop): ctx = papi.ProtocolContext(loop) # TODO Ian 2019-05-29 load fixtures, not real defs labware_name = 'biorad_96_wellplate_200ul_pcr' labware_def = json.loads( load_shared_data(f'labware/definitions/2/{labware_name}/1.json')) mod = ctx.load_module('magdeck', 1) assert mod.labware is None mod.engage(height=45) assert mod._module.current_height == 45 with pytest.raises(ValueError): mod.engage(height=45.1) # max engage height for gen1 is 45 mm mod.load_labware(labware_name) mod.engage() lw_offset = labware_def['parameters']['magneticModuleEngageHeight'] assert mod._module._driver.plate_height == lw_offset mod.disengage() mod.engage(offset=2) assert mod._module._driver.plate_height == lw_offset + 2 mod.disengage() mod.engage(height=3) assert mod._module._driver.plate_height == 3 mod._geometry.reset_labware() labware_name = 'corning_96_wellplate_360ul_flat' mod.load_labware(labware_name) with pytest.raises(ValueError): mod.engage() with pytest.raises(ValueError): mod.engage(offset=1) mod.engage(height=2) assert mod._module._driver.plate_height == 2 mod.engage(height=0) assert mod._module._driver.plate_height == 0 mod.engage(height_from_base=2) assert mod._module._driver.plate_height == 2 +\ OFFSET_TO_LABWARE_BOTTOM[mod._module.model()]
def name_config() -> Dict[str, Any]: """ Load the per-pipette-name config file from within the wheel """ return json.loads( load_shared_data('pipette/definitions/pipetteNameSpecs.json') or '{}')
def dummy_load(labware_name, namespace=None, version=None): # TODO: Ian 2019-05-30 use fixtures not real defs labware_def = json.loads( load_shared_data(f'labware/definitions/2/{labware_name}/1.json')) return labware_def
import json from unittest.mock import patch from numpy import isclose import pytest from opentrons import types from opentrons.config import pipette_config, feature_flags as ff, CONFIG from opentrons.system.shared_data import load_shared_data defs = json.loads( load_shared_data("pipette/definitions/pipetteModelSpecs.json")) def check_sequences_close(first, second): """ Check two ul/mm sequences are the same (replaces pytest.approx nested ) """ assert len(first) == len(second) for f, s in zip(first, second): assert f == pytest.approx(s) @pytest.mark.parametrize('pipette_model', [ c for c in pipette_config.config_models if not (c.startswith('p1000') or c.startswith('p300_multi') or c.endswith('1.5') or c.endswith('1.6') or 'v2' in c) ]) def test_versioned_aspiration(pipette_model, monkeypatch): monkeypatch.setattr(ff, 'use_old_aspiration_functions', lambda: True)