{"action":"created","issue":{"url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/121","labels_url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/121/labels{/name}","comments_url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/121/comments","events_url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/121/events","html_url":"https://github.com/autodesk-bionano/genome-designer/pull/121","id":121347867,"number":121,"title":"Genbank parser as a \"Node\" extension","user":{"login":"dchandran","id":586734,"avatar_url":"https://avatars.githubusercontent.com/u/586734?v=3","gravatar_id":"","url":"https://api.github.com/users/dchandran","html_url":"https://github.com/dchandran","followers_url":"https://api.github.com/users/dchandran/followers","following_url":"https://api.github.com/users/dchandran/following{/other_user}","gists_url":"https://api.github.com/users/dchandran/gists{/gist_id}","starred_url":"https://api.github.com/users/dchandran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dchandran/subscriptions","organizations_url":"https://api.github.com/users/dchandran/orgs","repos_url":"https://api.github.com/users/dchandran/repos","events_url":"https://api.github.com/users/dchandran/events{/privacy}","received_events_url":"https://api.github.com/users/dchandran/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-12-09T21:54:19Z","updated_at":"2015-12-10T00:12:03Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/autodesk-bionano/genome-designer/pulls/121","html_url":"https://github.com/autodesk-bionano/genome-designer/pull/121","diff_url":"https://github.com/autodesk-bionano/genome-designer/pull/121.diff","patch_url":"https://github.com/autodesk-bionano/genome-designer/pull/121.patch"},"body":"This pull request has the extensions framework and has the genbank parser as an example. The extensions framework uses the same interface as the platform that Dion is developing. The genbank parser is implemented in Docker so that the main server does not need to install python and biopython (and everything else that each extension would require) - it keeps the requirements modular.\r\n\r\nThe /extensions/compute folder has all the \"node\" extensions.\r\nThe /extensions/foundry folder has the \"toy\" foundry API example and all of E.coli genes as an example inventory (block data format).\r\n\r\n@IsaacLuo check if the code below is sufficient for Onion.\r\n\r\nBelow is the code that Onion would need to execute. The first REST call is for executing the genbank parse code. The second is to update the block in the server database because the parser program just returns the block object. The code is basically two REST calls.\r\n```\r\n#save selected block ID\r\nvar block_id = block.id; \r\n\r\n#tell the extension what to use as input and\r\n#where to write the output\r\n#any output that does not have a file specified \r\n#will be returned in the json\r\n\r\nvar inputs = {\r\n  \"genbank\":\"extensions/compute/genbank_to_block/sequence.gb\", \r\n  \"sequence\":\"storage/block/\"+block_id+\"/sequence\"\r\n}\r\n\r\n#Call the genbank extension\r\nvar output;\r\nvar onion_data;\r\n\r\nfetch(run_url + \"genbank_to_block\", {\r\n        method: 'post',\r\n        headers: headers,\r\n        body: JSON.stringify(inputs) #input\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    \r\n    #get the block and onion_data from the results\r\n    output = resp;\r\n    block = JSON.parse(output.block)    \r\n    data = JSON.parse(output.onion_data)\r\n\r\n});\r\n\r\n#We need to update block sequence URL\r\n#because the genbank extension currently\r\n#does not write anything to the database\r\n\r\nblock.id = block_id\r\nblock.sequence.url = inputs.sequence\r\n\r\nfetch(api_url + \"block/\" + block_id, {\r\n        method: 'put',\r\n        headers: headers,\r\n        body: JSON.stringify(block)\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    console.log(\"success\");\r\n});\r\n```\r\n\r\nThe above code assumes that you already have the session-key and a block. Here is an example code for generating those. After doing npm run start, you can run the code below in the Chrome console directly (within the app, i.e. 0.0.0.0:3000).\r\n\r\n```\r\nvar api_url = \"api/\";\r\nvar run_url = \"exec/\";\r\nvar headers = {  \"Content-type\": \"application/json\" };\r\nvar block;\r\nvar input;\r\nvar output;\r\n\r\n/*****\r\nYou need to do this once, just to get a session key\r\nThe client side would cache this and automatically\r\nappend session-key to all requests \r\n******/\r\n\r\nfetch(api_url + \"login?user=''&password=''\", {\r\n        method: 'get',\r\n        headers: headers\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    headers[\"session-key\"] = resp[\"session-key\"];\r\n});\r\n\r\n/*********\r\nCreate a block. In the app itself, Onion would not need\r\nto create a block because a block will already exist, \r\nso this step is not needed.\r\n*********/\r\n\r\nblock = {\r\n  \"metadata\": {\r\n    \"authors\": [],\r\n    \"version\": \"0.0.0\",\r\n    \"tags\": {}  },\r\n  \"options\":[],\r\n  \"components\":[],\r\n  \"rules\": [],\r\n  \"notes\": {}\r\n}\r\n\r\nfetch(api_url + \"block\", {\r\n        method: 'post',\r\n        headers: headers,\r\n        body: JSON.stringify(block)\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    block = resp;\r\n});\r\n\r\n/*********\r\nThis is what Onion would do\r\n**********/\r\n\r\n#save block id\r\nvar block_id = block.id; \r\n\r\n#tell the extension what to use as input and\r\n#where to write the output\r\n#any output that does not have a file specified \r\n#will be returned in the json\r\n\r\nvar inputs = {\r\n  \"genbank\":\"extensions/compute/genbank_to_block/sequence.gb\", \r\n  \"sequence\":\"storage/block/\"+block_id+\"/sequence\"\r\n}\r\n\r\n#Call the genbank extension\r\nvar output;\r\nvar onion_data;\r\n\r\nfetch(run_url + \"genbank_to_block\", {\r\n        method: 'post',\r\n        headers: headers,\r\n        body: JSON.stringify(inputs) #input\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    \r\n    #get the block and onion_data from the results\r\n    output = resp;\r\n    block = JSON.parse(output.block)    \r\n    data = JSON.parse(output.onion_data)\r\n\r\n});\r\n\r\n\r\n#We need to update block sequence URL\r\n#because the genbank extension currently\r\n#does not write anything to the database\r\n\r\nblock.id = block_id\r\nblock.sequence.url = inputs.sequence\r\n\r\nfetch(api_url + \"block/\" + block_id, {\r\n        method: 'put',\r\n        headers: headers,\r\n        body: JSON.stringify(block)\r\n}).then( function(resp) {\r\n    return resp.json();\r\n}).then( function(resp) {\r\n    console.log(\"success\");\r\n});\r\n```\r\n\r\n\r\nPython test case that tests the above scenario (need to move these to JS at some point).\r\n```\r\n$ipython server/api/api_test.py \r\n----------------------------------------------------------------------\r\nRan 7 tests in 11.664s\r\n\r\nOK\r\n```"},"comment":{"url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/comments/163443234","html_url":"https://github.com/autodesk-bionano/genome-designer/pull/121#issuecomment-163443234","issue_url":"https://api.github.com/repos/autodesk-bionano/genome-designer/issues/121","id":163443234,"user":{"login":"maxbates","id":3815620,"avatar_url":"https://avatars.githubusercontent.com/u/3815620?v=3","gravatar_id":"","url":"https://api.github.com/users/maxbates","html_url":"https://github.com/maxbates","followers_url":"https://api.github.com/users/maxbates/followers","following_url":"https://api.github.com/users/maxbates/following{/other_user}","gists_url":"https://api.github.com/users/maxbates/gists{/gist_id}","starred_url":"https://api.github.com/users/maxbates/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maxbates/subscriptions","organizations_url":"https://api.github.com/users/maxbates/orgs","repos_url":"https://api.github.com/users/maxbates/repos","events_url":"https://api.github.com/users/maxbates/events{/privacy}","received_events_url":"https://api.github.com/users/maxbates/received_events","type":"User","site_admin":false},"created_at":"2015-12-10T00:12:03Z","updated_at":"2015-12-10T00:12:03Z","body":"Setting sequence should also set the length field on the sequence"}}