class TestManifest: @pytest.fixture(autouse=True) def setUp(self): self.protocol = Protocol() def test_empty(self): protocol_info = ProtocolInfo({'name': 'Test Empty', 'inputs': {}}) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert ({} == parsed) def test_basic_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'bool': 'bool', 'string': 'string', 'integer': 'integer', 'decimal': 'decimal' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 } }) assert ({ 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 } == parsed) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "hi", 'decimal': 2.1 } }) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "3", 'decimal': "hi" } }) def test_unit_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'volume': 'volume', 'time': 'time', 'temperature': 'temperature' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': '3:microliter', 'time': '30:second', 'temperature': '25:celsius' } }) assert ({ 'volume': Unit.fromstring('3:microliter'), 'time': Unit.fromstring('30:second'), 'temperature': Unit.fromstring('25:celsius') } == parsed) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': 3, 'time': '30:second', 'temperature': '25:celsius' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "hello", 'temperature': '25:celsius' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "30:second", 'temperature': 25 } }) def test_group(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': { 'test': 'ct1test/0' } } }) assert (isinstance(parsed['group_test'], dict)) assert ('test' in parsed['group_test']) assert (isinstance(parsed['group_test']['test'], Well)) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } } } }) protocol_info1.parse(self.protocol, { 'refs': {}, 'parameters': { 'group': ["hello"] } }) with pytest.raises(RuntimeError): protocol_info2 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group' } } }) protocol_info2.parse( self.protocol, { 'refs': {}, 'parameters': { 'group': { "bool": True, "aliquot": "dummy/0", "aliquot+": ["dummy/0"] } } }) def test_multigroup(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': [{ 'test': 'ct1test/0' }, { 'test': 'ct1test/1' }] } }) assert (isinstance(parsed['group_test'], list)) assert (2 == len(parsed['group_test'])) assert ('test' in parsed['group_test'][0]) assert (isinstance(parsed['group_test'][0]['test'], Well)) assert ('test' in parsed['group_test'][1]) assert (isinstance(parsed['group_test'][1]['test'], Well)) assert (1 == parsed['group_test'][1]['test'].index) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': { 'test': 'ct1test/0', 'test': 'ct1test/1' } } }) protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+' } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': [{ 'test': 'ct1test/0' }, { 'test': 'ct1test/1' }] } }) def test_group_choice(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group-choice', 'options': [{ 'value': 'a', 'inputs': { 'test': 'aliquot' } }, { 'value': 'b' }] } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': { 'value': 'a', 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': {} } } } }) assert (isinstance(parsed['group_test'], dict)) assert ('a' == parsed['group_test']['value']) assert ('a' in parsed['group_test']['inputs']) assert ('b' not in parsed['group_test']['inputs']) assert (isinstance(parsed['group_test']['inputs']['a']['test'], Well)) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': { 'value': 'a' } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': '96-pcr', 'discard': True } }, 'parameters': { 'group_test': { 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': {} } } } }) def test_csv_table(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { "table_test": { "template": { "header": [ "Destination Well", "Source Well", "Final concentration in ug/ml" ], "keys": [ "dest_well", "source_well", "final_concentration_ugml" ], "col_type": ["integer", "aliquot", "decimal"], "rows": [["0", "ct17652537/0", "1.2"], ["1", "ct17652537/0", "4.37"]], "label": "Test Table CSV" }, "type": "csv-table", "label": "test table label" } } }) parsed = protocol_info.parse( self.protocol, { 'refs': { 'ct1test': { 'id': 'ct1test', 'type': 'micro-1.5', 'discard': True }, 'ct2test': { 'id': 'ct2test', 'type': 'micro-1.5', 'discard': True } }, 'parameters': { "table_test": [{ "dest_well": "integer", "source_well": "aliquot", "final_concentration_ugml": "decimal" }, [{ "dest_well": 0, "source_well": "ct1test/0", "final_concentration_ugml": 0.5 }, { "dest_well": 1, "source_well": "ct2test/0", "final_concentration_ugml": 0.6 }]] } }) assert (isinstance(parsed['table_test'], list)) assert (isinstance(parsed['table_test'][0], dict)) assert ('final_concentration_ugml' in parsed['table_test'][0]) assert (isinstance(parsed['table_test'][1]['source_well'], Well)) def test_blank_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'int': 'integer', 'str': 'string', 'bool': 'bool', 'decimal': 'decimal', 'volume': 'volume', 'temperature': 'temperature', 'csv-table': 'csv-table' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert (parsed['int'] is None) assert (parsed['str'] is None) assert (parsed['bool'] is None) assert (parsed['decimal'] is None) assert (parsed['volume'] is None) assert (parsed['temperature'] is None) assert isinstance(parsed['csv-table'], list) def test_ref_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'aliquot': 'aliquot', 'aliquot+': 'aliquot+', 'aliquot++': 'aliquot++', 'container': 'container', 'container+': 'container+' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert (parsed['aliquot'] is None) assert (parsed['container'] is None) assert isinstance(parsed['aliquot+'], WellGroup) assert (0 == len(parsed['aliquot+'])) assert ([] == parsed['aliquot++']) assert ([] == parsed['container+']) def test_group_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } }, 'group+': { 'type': 'group+', 'inputs': { 'bool': 'bool' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert isinstance(parsed['group'], dict) assert (parsed['group']['bool'] is None) assert (parsed['group']['aliquot'] is None) assert isinstance(parsed['group']['aliquot+'], WellGroup) assert (0 == len(parsed['group']['aliquot+'])) assert ([{'bool': None}] == parsed['group+']) def test_container_errors(self): with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse( self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "my_cont/0" } }) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse( self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "another_cont" } }) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse( self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": 12 } }) def test_container_volumes(self): protocol_info1 = ProtocolInfo({ 'name': 'Test Container Volumes', 'inputs': { 'cont': { 'type': 'container' } } }) parsed = protocol_info1.parse( self.protocol, { "refs": { "echo_plate": { "type": "384-echo", "discard": True, "aliquots": { "0": { "volume": "135:microliter" } } } }, "parameters": { "cont": "echo_plate" } }) assert parsed["cont"].well(0).volume == Unit(135, "microliter") with pytest.raises(ValueError) as e: protocol_info1.parse( self.protocol, { 'refs': { "my_cont": { "type": "384-echo", "discard": True, "aliquots": { "0": { "volume": "10000:microliter" } } } }, 'parameters': { "cont": "my_cont" } }) assert "Theoretical volume" in str(e.value) # Test parsing of local manifest file def test_json_parse(self): with open('test/manifest_test.json', 'r') as f: manifest_json = f.read() manifest = Manifest(json.loads(manifest_json)) source = json.loads(manifest_json)['protocols'][0]['preview'] manifest.protocol_info('TestMethod').parse(self.protocol, source) def test_seal_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-pcr", storage="cold_20") test2 = self.protocol.ref("test2", None, "96-flat", storage="cold_20", cover="standard") self.protocol.spin(test, "2000:g", "5:minute") self.protocol.spin(test2, "2000:g", "5:minute") assert (len(self.protocol.instructions) == 3) self.protocol.uncover(test2) seal_on_store(self.protocol) assert (len(self.protocol.instructions) == 5) assert (self.protocol.instructions[-1].op == "cover") assert (self.protocol.instructions[-1].lid == "low_evaporation") self.protocol.uncover(test2) seal_on_store(self.protocol) assert (len(self.protocol.instructions) == 7) assert (self.protocol.instructions[-1].op == "cover") assert (self.protocol.instructions[-1].lid == "low_evaporation") def test_seal_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "384-pcr", storage="cold_20") self.protocol.seal(test, "foil") self.protocol.unseal(test) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].type == "ultra-clear") test2 = self.protocol.ref("test2", None, "384-pcr", storage="cold_20") self.protocol.seal(test2, "ultra-clear") self.protocol.unseal(test2) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].type == "ultra-clear") def test_cover_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test, "universal") self.protocol.uncover(test) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].lid == "low_evaporation") test2 = self.protocol.ref("test2", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test2) self.protocol.uncover(test2) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].lid == "low_evaporation")
class TestManifest(object): @pytest.fixture(autouse=True) def setUp(self): self.protocol = Protocol() def test_empty(self): protocol_info = ProtocolInfo({"name": "Test Empty", "inputs": {}}) parsed = protocol_info.parse(self.protocol, { "refs": {}, "parameters": {} }) assert {} == parsed def test_basic_types(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "bool": "bool", "string": "string", "integer": "integer", "decimal": "decimal", }, }) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "bool": True, "string": "test", "integer": 3, "decimal": 2.1, }, }, ) assert { "bool": True, "string": "test", "integer": 3, "decimal": 2.1 } == parsed with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "bool": True, "string": "test", "integer": "hi", "decimal": 2.1, }, }, ) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "bool": True, "string": "test", "integer": "3", "decimal": "hi", }, }, ) def test_unit_types(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "volume": "volume", "time": "time", "temperature": "temperature", }, }) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "30:second", "temperature": "25:celsius", }, }, ) assert { "volume": Unit.fromstring("3:microliter"), "time": Unit.fromstring("30:second"), "temperature": Unit.fromstring("25:celsius"), } == parsed with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": 3, "time": "30:second", "temperature": "25:celsius", }, }, ) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "hello", "temperature": "25:celsius", }, }, ) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "30:second", "temperature": 25, }, }, ) def test_group(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "group_test": { "type": "group", "inputs": { "test": "aliquot" } } }, }) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": { "test": "ct1test/0" } }, }, ) assert isinstance(parsed["group_test"], dict) assert "test" in parsed["group_test"] assert isinstance(parsed["group_test"]["test"], Well) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ "name": "Test Errors", "inputs": { "group": { "type": "group", "inputs": { "bool": "bool", "aliquot": "aliquot", "aliquot+": "aliquot+", }, } }, }) protocol_info1.parse(self.protocol, { "refs": {}, "parameters": { "group": ["hello"] } }) with pytest.raises(RuntimeError): protocol_info2 = ProtocolInfo({ "name": "Test Errors", "inputs": { "group": { "type": "group" } } }) protocol_info2.parse( self.protocol, { "refs": {}, "parameters": { "group": { "bool": True, "aliquot": "dummy/0", "aliquot+": ["dummy/0"], } }, }, ) def test_multigroup(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "group_test": { "type": "group+", "inputs": { "test": "aliquot" } } }, }) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": [{ "test": "ct1test/0" }, { "test": "ct1test/1" }] }, }, ) assert isinstance(parsed["group_test"], list) assert 2 == len(parsed["group_test"]) assert "test" in parsed["group_test"][0] assert isinstance(parsed["group_test"][0]["test"], Well) assert "test" in parsed["group_test"][1] assert isinstance(parsed["group_test"][1]["test"], Well) assert 1 == parsed["group_test"][1]["test"].index # pragma pylint: disable=duplicate-key with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": { "test": "ct1test/0", "test": "ct1test/1" } }, }, ) protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "group_test": { "type": "group+" } }, }) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": [{ "test": "ct1test/0" }, { "test": "ct1test/1" }] }, }, ) # pragma pylint: enable=duplicate-key def test_group_choice(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "group_test": { "type": "group-choice", "options": [ { "value": "a", "inputs": { "test": "aliquot" } }, { "value": "b" }, ], } }, }) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": { "value": "a", "inputs": { "a": { "test": "ct1test/0" }, "b": {} }, } }, }, ) assert isinstance(parsed["group_test"], dict) assert "a" == parsed["group_test"]["value"] assert "a" in parsed["group_test"]["inputs"] assert "b" not in parsed["group_test"]["inputs"] assert isinstance(parsed["group_test"]["inputs"]["a"]["test"], Well) with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": { "value": "a" } }, }, ) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "96-pcr", "discard": True } }, "parameters": { "group_test": { "inputs": { "a": { "test": "ct1test/0" }, "b": {} } } }, }, ) def test_csv_table(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "table_test": { "template": { "header": [ "Destination Well", "Source Well", "Final concentration in ug/ml", ], "keys": [ "dest_well", "source_well", "final_concentration_ugml", ], "col_type": ["integer", "aliquot", "decimal"], "rows": [ ["0", "ct17652537/0", "1.2"], ["1", "ct17652537/0", "4.37"], ], "label": "Test Table CSV", }, "type": "csv-table", "label": "test table label", } }, }) parsed = protocol_info.parse( self.protocol, { "refs": { "ct1test": { "id": "ct1test", "type": "micro-1.5", "discard": True }, "ct2test": { "id": "ct2test", "type": "micro-1.5", "discard": True }, }, "parameters": { "table_test": [ { "dest_well": "integer", "source_well": "aliquot", "final_concentration_ugml": "decimal", }, [ { "dest_well": 0, "source_well": "ct1test/0", "final_concentration_ugml": 0.5, }, { "dest_well": 1, "source_well": "ct2test/0", "final_concentration_ugml": 0.6, }, ], ] }, }, ) assert isinstance(parsed["table_test"], list) assert isinstance(parsed["table_test"][0], dict) assert "final_concentration_ugml" in parsed["table_test"][0] assert isinstance(parsed["table_test"][1]["source_well"], Well) def test_blank_default(self): protocol_info = ProtocolInfo({ "name": "Test Basic Blank Defaults", "inputs": { "int": "integer", "str": "string", "bool": "bool", "decimal": "decimal", "volume": "volume", "temperature": "temperature", "csv-table": "csv-table", }, }) parsed = protocol_info.parse(self.protocol, { "refs": {}, "parameters": {} }) assert parsed["int"] is None assert parsed["str"] is None assert parsed["bool"] is None assert parsed["decimal"] is None assert parsed["volume"] is None assert parsed["temperature"] is None assert isinstance(parsed["csv-table"], list) def test_ref_default(self): protocol_info = ProtocolInfo({ "name": "Test Basic Blank Defaults", "inputs": { "aliquot": "aliquot", "aliquot+": "aliquot+", "aliquot++": "aliquot++", "container": "container", "container+": "container+", }, }) parsed = protocol_info.parse(self.protocol, { "refs": {}, "parameters": {} }) assert parsed["aliquot"] is None assert parsed["container"] is None assert isinstance(parsed["aliquot+"], WellGroup) assert 0 == len(parsed["aliquot+"]) assert [] == parsed["aliquot++"] assert [] == parsed["container+"] def test_group_default(self): protocol_info = ProtocolInfo({ "name": "Test Basic Blank Defaults", "inputs": { "group": { "type": "group", "inputs": { "bool": "bool", "aliquot": "aliquot", "aliquot+": "aliquot+", }, }, "group+": { "type": "group+", "inputs": { "bool": "bool" } }, }, }) parsed = protocol_info.parse(self.protocol, { "refs": {}, "parameters": {} }) assert isinstance(parsed["group"], dict) assert parsed["group"]["bool"] is None assert parsed["group"]["aliquot"] is None assert isinstance(parsed["group"]["aliquot+"], WellGroup) assert 0 == len(parsed["group"]["aliquot+"]) assert [{"bool": None}] == parsed["group+"] def test_container_errors(self): with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ "name": "Test Errors", "inputs": { "cont": { "type": "container" } } }) protocol_info1.parse( self.protocol, { "refs": { "my_cont": { "type": "micro-1.5", "discard": True } }, "parameters": { "cont": "my_cont/0" }, }, ) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ "name": "Test Errors", "inputs": { "cont": { "type": "container" } } }) protocol_info1.parse( self.protocol, { "refs": { "my_cont": { "type": "micro-1.5", "discard": True } }, "parameters": { "cont": "another_cont" }, }, ) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ "name": "Test Errors", "inputs": { "cont": { "type": "container" } } }) protocol_info1.parse( self.protocol, { "refs": { "my_cont": { "type": "micro-1.5", "discard": True } }, "parameters": { "cont": 12 }, }, ) def test_container_volumes(self): protocol_info1 = ProtocolInfo({ "name": "Test Container Volumes", "inputs": { "cont": { "type": "container" } }, }) parsed = protocol_info1.parse( self.protocol, { "refs": { "echo_plate": { "type": "384-echo", "discard": True, "aliquots": { "0": { "volume": "135:microliter" } }, } }, "parameters": { "cont": "echo_plate" }, }, ) assert parsed["cont"].well(0).volume == Unit(135, "microliter") with pytest.raises(ValueError) as e: protocol_info1.parse( self.protocol, { "refs": { "my_cont": { "type": "384-echo", "discard": True, "aliquots": { "0": { "volume": "10000:microliter" } }, } }, "parameters": { "cont": "my_cont" }, }, ) assert "Theoretical volume" in str(e.value) # Test parsing of local manifest file def test_json_parse(self): with open("test/manifest_test.json", "r") as f: manifest_json = f.read() manifest = Manifest(json.loads(manifest_json)) source = json.loads(manifest_json)["protocols"][0]["preview"] manifest.protocol_info("TestMethod").parse(self.protocol, source) def test_seal_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-pcr", storage="cold_20") test2 = self.protocol.ref("test2", None, "96-flat", storage="cold_20", cover="standard") self.protocol.spin(test, "2000:g", "5:minute") self.protocol.spin(test2, "2000:g", "5:minute") assert len(self.protocol.instructions) == 3 self.protocol.uncover(test2) seal_on_store(self.protocol) assert len(self.protocol.instructions) == 5 assert self.protocol.instructions[-1].op == "cover" assert self.protocol.instructions[-1].lid == "low_evaporation" self.protocol.uncover(test2) seal_on_store(self.protocol) assert len(self.protocol.instructions) == 7 assert self.protocol.instructions[-1].op == "cover" assert self.protocol.instructions[-1].lid == "low_evaporation" def test_seal_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "384-pcr", storage="cold_20") self.protocol.seal(test, "foil") self.protocol.unseal(test) seal_on_store(self.protocol) assert self.protocol.instructions[-1].type == "ultra-clear" test2 = self.protocol.ref("test2", None, "384-pcr", storage="cold_20") self.protocol.seal(test2, "ultra-clear") self.protocol.unseal(test2) seal_on_store(self.protocol) assert self.protocol.instructions[-1].type == "ultra-clear" def test_cover_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test, "universal") self.protocol.uncover(test) seal_on_store(self.protocol) assert self.protocol.instructions[-1].lid == "low_evaporation" test2 = self.protocol.ref("test2", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test2) self.protocol.uncover(test2) seal_on_store(self.protocol) assert self.protocol.instructions[-1].lid == "low_evaporation" def test_get_protocol_preview(self): preview = get_protocol_preview(self.protocol, "TestMethod", manifest="test/manifest_test.json") manifest_keys = [ "my_string", "my_container", "my_volume", "my_length", "my_bool", ] for key in manifest_keys: assert key in preview def test_compound_type(self): protocol_info1 = ProtocolInfo({ "name": "Test Compound type", "inputs": { "compound": { "type": "compound" } }, }) parsed = protocol_info1.parse( self.protocol, { "refs": {}, "parameters": { "compound": { "format": "InChI", "value": "InChI=1S/CH4/h1H4" } }, }, ) assert parsed["compound"].value == "InChI=1S/CH4/h1H4" def test_multiple_compound_type(self): protocol_info1 = ProtocolInfo({ "name": "Test Compound type", "inputs": { "compound": { "type": "compound+" } }, }) parsed = protocol_info1.parse( self.protocol, { "refs": {}, "parameters": { "compound": [ { "format": "Daylight Canonical SMILES", "value": "C1=CC=CC=C1" }, { "format": "Daylight Canonical SMILES", "value": "CCCC" }, ] }, }, ) assert parsed["compound"][0].value == "C1=CC=CC=C1" assert parsed["compound"][0].format == "Daylight Canonical SMILES" assert parsed["compound"][1].value == "CCCC" assert parsed["compound"][1].format == "Daylight Canonical SMILES" def test_invalid_compound(self): with pytest.raises(RuntimeError) as e: protocol_info1 = ProtocolInfo({ "name": "Test Compound type", "inputs": { "compound": { "type": "compound" } }, }) protocol_info1.parse( self.protocol, { "refs": {}, "parameters": { "compound": { "format": "Daylight Canonical SMILES", "value": "C1:CO&", } }, }, ) assert "C1:CO& is not a valid Daylight Canonical SMILES value." in str( e.value) with pytest.raises(RuntimeError) as e: protocol_info1 = ProtocolInfo({ "name": "Test Compound type", "inputs": { "compound": { "type": "compound" } }, }) protocol_info1.parse( self.protocol, { "refs": {}, "parameters": { "compound": { "format": "foo", "value": "CCCC" } }, }, ) assert "foo is not an acceptable Compound format." in str(e.value)
class ManifestTest(unittest.TestCase): def setUp(self): self.protocol = Protocol() def test_empty(self): protocol_info = ProtocolInfo({ 'name': 'Test Empty', 'inputs': {} }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) self.assertEqual({}, parsed) def test_basic_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'bool': 'bool', 'string': 'string', 'integer': 'integer', 'decimal': 'decimal' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 } }) self.assertEqual({ 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 }, parsed) with self.assertRaises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "hi", 'decimal': 2.1 } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "3", 'decimal': "hi" } }) def test_unit_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'volume': 'volume', 'time': 'time', 'temperature': 'temperature' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': '3:microliter', 'time': '30:second', 'temperature': '25:celsius' } }) self.assertEqual({ 'volume': Unit.fromstring('3:microliter'), 'time': Unit.fromstring('30:second'), 'temperature': Unit.fromstring('25:celsius') }, parsed) with self.assertRaises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': 3, 'time': '30:second', 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "hello", 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "30:second", 'temperature': 25 } }) def test_group(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'test': 'ct1test/0' } } }) self.assertTrue(isinstance(parsed['group_test'], dict)) self.assertTrue('test' in parsed['group_test']) self.assertTrue(isinstance(parsed['group_test']['test'], Well)) with self.assertRaises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } } } }) protocol_info1.parse(self.protocol, { 'refs': { }, 'parameters': { 'group': ["hello"] } }) protocol_info2 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group' } } }) protocol_info2.parse(self.protocol, { 'refs': { }, 'parameters': { 'group': { "bool": True, "aliquot": "dummy/0", "aliquot+": ["dummy/0"] } } }) def test_multigroup(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': [ {'test': 'ct1test/0'}, {'test': 'ct1test/1'} ] } }) self.assertTrue(isinstance(parsed['group_test'], list)) self.assertEqual(2, len(parsed['group_test'])) self.assertTrue('test' in parsed['group_test'][0]) self.assertTrue(isinstance(parsed['group_test'][0]['test'], Well)) self.assertTrue('test' in parsed['group_test'][1]) self.assertTrue(isinstance(parsed['group_test'][1]['test'], Well)) self.assertEqual(1, parsed['group_test'][1]['test'].index) with self.assertRaises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'test': 'ct1test/0', 'test': 'ct1test/1' } } }) protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+' } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': [ {'test': 'ct1test/0'}, {'test': 'ct1test/1'} ] } }) def test_group_choice(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group-choice', 'options': [ { 'value': 'a', 'inputs': { 'test': 'aliquot' } }, { 'value': 'b' } ] } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'value': 'a', 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': { } } } } }) self.assertTrue(isinstance(parsed['group_test'], dict)) self.assertEqual('a', parsed['group_test']['value']) self.assertTrue('a' in parsed['group_test']['inputs']) self.assertFalse('b' in parsed['group_test']['inputs']) self.assertTrue( isinstance(parsed['group_test']['inputs']['a']['test'], Well)) with self.assertRaises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'value': 'a' } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': { } } } } }) def test_csv_table(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { "table_test": { "template": { "header": ["Destination Well", "Source Well", "Final concentration in ug/ml"], "keys": ["dest_well", "source_well", "final_concentration_ugml"], "col_type": ["integer", "aliquot", "decimal"], "rows": [ ["0", "ct17652537/0", "1.2"], ["1", "ct17652537/0", "4.37"] ], "label": "Test Table CSV" }, "type": "csv-table", "label": "test table label" } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': 'micro-1.5', 'discard': True}, 'ct2test': {'id': 'ct2test', 'type': 'micro-1.5', 'discard': True} }, 'parameters': { "table_test": [ { "dest_well": "integer", "source_well": "aliquot", "final_concentration_ugml": "decimal" }, [ { "dest_well": 0, "source_well": "ct1test/0", "final_concentration_ugml": 0.5 }, { "dest_well": 1, "source_well": "ct2test/0", "final_concentration_ugml": 0.6 } ] ] } }) self.assertTrue(isinstance(parsed['table_test'], list)) self.assertTrue(isinstance(parsed['table_test'][0], dict)) self.assertTrue('final_concentration_ugml' in parsed['table_test'][0]) self.assertTrue(isinstance(parsed['table_test'][1]['source_well'], Well)) def test_blank_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'int': 'integer', 'str': 'string', 'bool': 'bool', 'decimal': 'decimal', 'volume': 'volume', 'temperature': 'temperature', 'csv-table': 'csv-table' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) self.assertIsNone(parsed['int']) self.assertIsNone(parsed['str']) self.assertIsNone(parsed['bool']) self.assertIsNone(parsed['decimal']) self.assertIsNone(parsed['volume']) self.assertIsNone(parsed['temperature']) self.assertIsInstance(parsed['csv-table'], list) def test_ref_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'aliquot': 'aliquot', 'aliquot+': 'aliquot+', 'aliquot++': 'aliquot++', 'container': 'container', 'container+': 'container+' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) self.assertIsNone(parsed['aliquot']) self.assertIsNone(parsed['container']) self.assertIsInstance(parsed['aliquot+'], WellGroup) self.assertEqual(0, len(parsed['aliquot+'])) self.assertEqual([], parsed['aliquot++']) self.assertEqual([], parsed['container+']) def test_group_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } }, 'group+': { 'type': 'group+', 'inputs': { 'bool': 'bool' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) self.assertIsInstance(parsed['group'], dict) self.assertIsNone(parsed['group']['bool']) self.assertIsNone(parsed['group']['aliquot']) self.assertIsInstance(parsed['group']['aliquot+'], WellGroup) self.assertEqual(0, len(parsed['group']['aliquot+'])) self.assertEqual([{'bool': None}], parsed['group+']) def test_container_errors(self): with self.assertRaises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "my_cont/0" } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "another_cont" } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": 12 } }) # Test parsing of local manifest file def test_json_parse(self): protocol = Protocol() with open('test/manifest_test.json', 'r') as f: manifest_json = f.read() manifest = Manifest(json.loads(manifest_json)) source = json.loads(manifest_json)['protocols'][0]['preview'] manifest.protocol_info('TestMethod').parse(protocol, source) def test_seal_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-pcr", storage="cold_20") test2 = self.protocol.ref("test2", None, "96-flat", storage="cold_20", cover="standard") self.protocol.spin(test, "2000:g", "5:minute") self.protocol.spin(test2, "2000:g", "5:minute") self.assertEqual(len(self.protocol.instructions), 3) self.protocol.uncover(test2) seal_on_store(self.protocol) self.assertEqual(len(self.protocol.instructions), 5) self.assertTrue(self.protocol.instructions[-1].op == "cover") self.assertTrue(self.protocol.instructions[-1].lid == "standard") self.protocol.uncover(test2) seal_on_store(self.protocol) self.assertEqual(len(self.protocol.instructions), 7) self.assertTrue(self.protocol.instructions[-1].op == "cover") self.assertTrue(self.protocol.instructions[-1].lid == "standard") def test_seal_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "384-pcr", storage="cold_20") self.protocol.seal(test, "foil") self.protocol.unseal(test) seal_on_store(self.protocol) self.assertTrue(self.protocol.instructions[-1].type == "ultra-clear") test2 = self.protocol.ref("test2", None, "384-pcr", storage="cold_20") self.protocol.seal(test2, "ultra-clear") self.protocol.unseal(test2) seal_on_store(self.protocol) self.assertTrue(self.protocol.instructions[-1].type == "ultra-clear") def test_cover_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test, "universal") self.protocol.uncover(test) seal_on_store(self.protocol) self.assertTrue(self.protocol.instructions[-1].lid == "standard") test2 = self.protocol.ref("test2", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test2) self.protocol.uncover(test2) seal_on_store(self.protocol) self.assertTrue(self.protocol.instructions[-1].lid == "standard")
class TestManifest(object): @pytest.fixture(autouse=True) def setUp(self): self.protocol = Protocol() def test_empty(self): protocol_info = ProtocolInfo({ 'name': 'Test Empty', 'inputs': {} }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert ({} == parsed) def test_basic_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'bool': 'bool', 'string': 'string', 'integer': 'integer', 'decimal': 'decimal' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 } }) assert ({ 'bool': True, 'string': 'test', 'integer': 3, 'decimal': 2.1 } == parsed) with pytest.raises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "hi", 'decimal': 2.1 } }) with pytest.raises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'bool': True, 'string': 'test', 'integer': "3", 'decimal': "hi" } }) def test_unit_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'volume': 'volume', 'time': 'time', 'temperature': 'temperature' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': '3:microliter', 'time': '30:second', 'temperature': '25:celsius' } }) assert ({ 'volume': Unit.fromstring('3:microliter'), 'time': Unit.fromstring('30:second'), 'temperature': Unit.fromstring('25:celsius') } == parsed) with pytest.raises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': 3, 'time': '30:second', 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "hello", 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "30:second", 'temperature': 25 } }) def test_group(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'test': 'ct1test/0' } } }) assert (isinstance(parsed['group_test'], dict)) assert ('test' in parsed['group_test']) assert (isinstance(parsed['group_test']['test'], Well)) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } } } }) protocol_info1.parse(self.protocol, { 'refs': { }, 'parameters': { 'group': ["hello"] } }) with pytest.raises(RuntimeError): protocol_info2 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'group': { 'type': 'group' } } }) protocol_info2.parse(self.protocol, { 'refs': { }, 'parameters': { 'group': { "bool": True, "aliquot": "dummy/0", "aliquot+": ["dummy/0"] } } }) def test_multigroup(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+', 'inputs': { 'test': 'aliquot' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': [ {'test': 'ct1test/0'}, {'test': 'ct1test/1'} ] } }) assert (isinstance(parsed['group_test'], list)) assert (2 == len(parsed['group_test'])) assert ('test' in parsed['group_test'][0]) assert (isinstance(parsed['group_test'][0]['test'], Well)) assert ('test' in parsed['group_test'][1]) assert (isinstance(parsed['group_test'][1]['test'], Well)) assert (1 == parsed['group_test'][1]['test'].index) # pragma pylint: disable=duplicate-key with pytest.raises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'test': 'ct1test/0', 'test': 'ct1test/1' } } }) protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group+' } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': [ {'test': 'ct1test/0'}, {'test': 'ct1test/1'} ] } }) # pragma pylint: enable=duplicate-key def test_group_choice(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'group_test': { 'type': 'group-choice', 'options': [ { 'value': 'a', 'inputs': { 'test': 'aliquot' } }, { 'value': 'b' } ] } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'value': 'a', 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': { } } } } }) assert (isinstance(parsed['group_test'], dict)) assert ('a' == parsed['group_test']['value']) assert ('a' in parsed['group_test']['inputs']) assert ('b' not in parsed['group_test']['inputs']) assert ( isinstance(parsed['group_test']['inputs']['a']['test'], Well)) with pytest.raises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'value': 'a' } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': '96-pcr', 'discard': True} }, 'parameters': { 'group_test': { 'inputs': { 'a': { 'test': 'ct1test/0' }, 'b': { } } } } }) def test_csv_table(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { "table_test": { "template": { "header": ["Destination Well", "Source Well", "Final concentration in ug/ml"], "keys": ["dest_well", "source_well", "final_concentration_ugml"], "col_type": ["integer", "aliquot", "decimal"], "rows": [ ["0", "ct17652537/0", "1.2"], ["1", "ct17652537/0", "4.37"] ], "label": "Test Table CSV" }, "type": "csv-table", "label": "test table label" } } }) parsed = protocol_info.parse(self.protocol, { 'refs': { 'ct1test': {'id': 'ct1test', 'type': 'micro-1.5', 'discard': True}, 'ct2test': {'id': 'ct2test', 'type': 'micro-1.5', 'discard': True} }, 'parameters': { "table_test": [ { "dest_well": "integer", "source_well": "aliquot", "final_concentration_ugml": "decimal" }, [ { "dest_well": 0, "source_well": "ct1test/0", "final_concentration_ugml": 0.5 }, { "dest_well": 1, "source_well": "ct2test/0", "final_concentration_ugml": 0.6 } ] ] } }) assert (isinstance(parsed['table_test'], list)) assert (isinstance(parsed['table_test'][0], dict)) assert ('final_concentration_ugml' in parsed['table_test'][0]) assert (isinstance(parsed['table_test'][1]['source_well'], Well)) def test_blank_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'int': 'integer', 'str': 'string', 'bool': 'bool', 'decimal': 'decimal', 'volume': 'volume', 'temperature': 'temperature', 'csv-table': 'csv-table' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert (parsed['int'] is None) assert (parsed['str'] is None) assert (parsed['bool'] is None) assert (parsed['decimal'] is None) assert (parsed['volume'] is None) assert (parsed['temperature'] is None) assert isinstance(parsed['csv-table'], list) def test_ref_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'aliquot': 'aliquot', 'aliquot+': 'aliquot+', 'aliquot++': 'aliquot++', 'container': 'container', 'container+': 'container+' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert (parsed['aliquot'] is None) assert (parsed['container'] is None) assert isinstance(parsed['aliquot+'], WellGroup) assert (0 == len(parsed['aliquot+'])) assert ([] == parsed['aliquot++']) assert ([] == parsed['container+']) def test_group_default(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Blank Defaults', 'inputs': { 'group': { 'type': 'group', 'inputs': { 'bool': 'bool', 'aliquot': 'aliquot', 'aliquot+': 'aliquot+' } }, 'group+': { 'type': 'group+', 'inputs': { 'bool': 'bool' } } } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': {} }) assert isinstance(parsed['group'], dict) assert (parsed['group']['bool'] is None) assert (parsed['group']['aliquot'] is None) assert isinstance(parsed['group']['aliquot+'], WellGroup) assert (0 == len(parsed['group']['aliquot+'])) assert ([{'bool': None}] == parsed['group+']) def test_container_errors(self): with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "my_cont/0" } }) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": "another_cont" } }) with pytest.raises(RuntimeError): protocol_info1 = ProtocolInfo({ 'name': 'Test Errors', 'inputs': { 'cont': { 'type': 'container' } } }) protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "micro-1.5", "discard": True } }, 'parameters': { "cont": 12 } }) def test_container_volumes(self): protocol_info1 = ProtocolInfo({ 'name': 'Test Container Volumes', 'inputs': { 'cont': { 'type': 'container' } } }) parsed = protocol_info1.parse(self.protocol, { "refs": { "echo_plate": { "type": "384-echo", "discard": True, "aliquots": { "0": {"volume": "135:microliter"} } } }, "parameters": { "cont": "echo_plate" } }) assert parsed["cont"].well(0).volume == Unit(135, "microliter") with pytest.raises(ValueError) as e: protocol_info1.parse(self.protocol, { 'refs': { "my_cont": { "type": "384-echo", "discard": True, "aliquots": { "0": {"volume": "10000:microliter"} } } }, 'parameters': { "cont": "my_cont" } }) assert "Theoretical volume" in str(e.value) # Test parsing of local manifest file def test_json_parse(self): with open('test/manifest_test.json', 'r') as f: manifest_json = f.read() manifest = Manifest(json.loads(manifest_json)) source = json.loads(manifest_json)['protocols'][0]['preview'] manifest.protocol_info('TestMethod').parse(self.protocol, source) def test_seal_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-pcr", storage="cold_20") test2 = self.protocol.ref("test2", None, "96-flat", storage="cold_20", cover="standard") self.protocol.spin(test, "2000:g", "5:minute") self.protocol.spin(test2, "2000:g", "5:minute") assert (len(self.protocol.instructions) == 3) self.protocol.uncover(test2) seal_on_store(self.protocol) assert (len(self.protocol.instructions) == 5) assert (self.protocol.instructions[-1].op == "cover") assert (self.protocol.instructions[-1].lid == "low_evaporation") self.protocol.uncover(test2) seal_on_store(self.protocol) assert (len(self.protocol.instructions) == 7) assert (self.protocol.instructions[-1].op == "cover") assert (self.protocol.instructions[-1].lid == "low_evaporation") def test_seal_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "384-pcr", storage="cold_20") self.protocol.seal(test, "foil") self.protocol.unseal(test) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].type == "ultra-clear") test2 = self.protocol.ref("test2", None, "384-pcr", storage="cold_20") self.protocol.seal(test2, "ultra-clear") self.protocol.unseal(test2) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].type == "ultra-clear") def test_cover_type_on_store(self): seal_on_store(self.protocol) test = self.protocol.ref("test", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test, "universal") self.protocol.uncover(test) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].lid == "low_evaporation") test2 = self.protocol.ref("test2", None, "96-flat-uv", storage="cold_20") self.protocol.cover(test2) self.protocol.uncover(test2) seal_on_store(self.protocol) assert (self.protocol.instructions[-1].lid == "low_evaporation")