\ No newline at end of file
diff --git a/kbase.yml b/kbase.yml
index 0976c20..89b2934 100644
--- a/kbase.yml
+++ b/kbase.yml
@@ -11,7 +11,7 @@ service-language:
python
module-version:
- 1.0.0
+ 1.1.0
owners:
[gaprice]
diff --git a/lib/kb_quast/authclient.py b/lib/kb_quast/authclient.py
new file mode 100644
index 0000000..844f9b0
--- /dev/null
+++ b/lib/kb_quast/authclient.py
@@ -0,0 +1,94 @@
+'''
+Created on Aug 1, 2016
+
+A very basic KBase auth client for the Python server.
+
+@author: gaprice@lbl.gov
+'''
+import time as _time
+import requests as _requests
+import threading as _threading
+import hashlib
+
+
+class TokenCache(object):
+ ''' A basic cache for tokens. '''
+
+ _MAX_TIME_SEC = 5 * 60 # 5 min
+
+ _lock = _threading.RLock()
+
+ def __init__(self, maxsize=2000):
+ self._cache = {}
+ self._maxsize = maxsize
+ self._halfmax = maxsize / 2 # int division to round down
+
+ def get_user(self, token):
+ token = hashlib.sha256(token.encode('utf-8')).hexdigest()
+ with self._lock:
+ usertime = self._cache.get(token)
+ if not usertime:
+ return None
+
+ user, intime = usertime
+ if _time.time() - intime > self._MAX_TIME_SEC:
+ return None
+ return user
+
+ def add_valid_token(self, token, user):
+ if not token:
+ raise ValueError('Must supply token')
+ if not user:
+ raise ValueError('Must supply user')
+ token = hashlib.sha256(token.encode('utf-8')).hexdigest()
+ with self._lock:
+ self._cache[token] = [user, _time.time()]
+ if len(self._cache) > self._maxsize:
+ sorted_items = sorted(
+ list(self._cache.items()),
+ key=(lambda v: v[1][1])
+ )
+ for i, (t, _) in enumerate(sorted_items):
+ if i <= self._halfmax:
+ del self._cache[t]
+ else:
+ break
+
+
+class KBaseAuth(object):
+ '''
+ A very basic KBase auth client for the Python server.
+ '''
+
+ _LOGIN_URL = 'https://kbase.us/services/auth/api/legacy/KBase/Sessions/Login'
+
+ def __init__(self, auth_url=None):
+ '''
+ Constructor
+ '''
+ self._authurl = auth_url
+ if not self._authurl:
+ self._authurl = self._LOGIN_URL
+ self._cache = TokenCache()
+
+ def get_user(self, token):
+ if not token:
+ raise ValueError('Must supply token')
+ user = self._cache.get_user(token)
+ if user:
+ return user
+
+ d = {'token': token, 'fields': 'user_id'}
+ ret = _requests.post(self._authurl, data=d)
+ if not ret.ok:
+ try:
+ err = ret.json()
+ except Exception as e:
+ ret.raise_for_status()
+ raise ValueError('Error connecting to auth service: {} {}\n{}'
+ .format(ret.status_code, ret.reason,
+ err['error']['message']))
+
+ user = ret.json()['user_id']
+ self._cache.add_valid_token(token, user)
+ return user
diff --git a/lib/kb_quast/kb_quastImpl.py b/lib/kb_quast/kb_quastImpl.py
index 9db34db..81d444e 100644
--- a/lib/kb_quast/kb_quastImpl.py
+++ b/lib/kb_quast/kb_quastImpl.py
@@ -53,9 +53,9 @@ class kb_quast:
# state. A method could easily clobber the state set by another while
# the latter method is running.
######################################### noqa
- VERSION = "0.0.6"
- GIT_URL = "https://github.com/kbaseapps/kb_quast.git"
- GIT_COMMIT_HASH = "8d29af55af662fa41442c0134dd90c45decd8cf4"
+ VERSION = "1.1.0"
+ GIT_URL = "https://github.com/kbaseapps/kb_quast"
+ GIT_COMMIT_HASH = "f6be7c27bbf44a0d65b0250dbdb8079b5df9d7ae"
#BEGIN_CLASS_HEADER
@@ -195,13 +195,15 @@ def run_QUAST_app(self, ctx, params):
QUAST as a Narrative application. workspace_name - the name of the
workspace where the KBaseReport object will be saved. assemblies -
the list of assemblies upon which QUAST will be run. force_glimmer
- - running '--glimmer' option regardless of assembly object size)
- -> structure: parameter "workspace_name" of String, parameter
- "assemblies" of list of type "assembly_ref" (An X/Y/Z style
- reference to a workspace object containing an assembly, either a
- KBaseGenomes.ContigSet or KBaseGenomeAnnotations.Assembly.),
- parameter "force_glimmer" of type "boolean" (A boolean - 0 for
- false, 1 for true. @range (0, 1))
+ - running '--glimmer' option regardless of assembly object size
+ min_contig_length - set the minimum size of contigs to process.
+ Defaults to 500, minimum allowed is 50.) -> structure: parameter
+ "workspace_name" of String, parameter "assemblies" of list of type
+ "assembly_ref" (An X/Y/Z style reference to a workspace object
+ containing an assembly, either a KBaseGenomes.ContigSet or
+ KBaseGenomeAnnotations.Assembly.), parameter "force_glimmer" of
+ type "boolean" (A boolean - 0 for false, 1 for true. @range (0,
+ 1)), parameter "min_contig_length" of Long
:returns: instance of type "QUASTAppOutput" (Output of the
run_quast_app function. report_name - the name of the
KBaseReport.Report workspace object. report_ref - the workspace
@@ -256,18 +258,20 @@ def run_QUAST(self, ctx, params):
be run. -OR- files - the list of FASTA files upon which QUAST will
be run. Optional arguments: make_handle - create a handle for the
new shock node for the report. force_glimmer - running '--glimmer'
- option regardless of file/assembly object size) -> structure:
- parameter "assemblies" of list of type "assembly_ref" (An X/Y/Z
- style reference to a workspace object containing an assembly,
- either a KBaseGenomes.ContigSet or
- KBaseGenomeAnnotations.Assembly.), parameter "files" of list of
- type "FASTAFile" (A local FASTA file. path - the path to the FASTA
- file. label - the label to use for the file in the QUAST output.
- If missing, the file name will be used.) -> structure: parameter
- "path" of String, parameter "label" of String, parameter
- "make_handle" of type "boolean" (A boolean - 0 for false, 1 for
- true. @range (0, 1)), parameter "force_glimmer" of type "boolean"
- (A boolean - 0 for false, 1 for true. @range (0, 1))
+ option regardless of file/assembly object size min_contig_length -
+ set the minimum size of contigs to process. Defaults to 500,
+ minimum allowed is 50.) -> structure: parameter "assemblies" of
+ list of type "assembly_ref" (An X/Y/Z style reference to a
+ workspace object containing an assembly, either a
+ KBaseGenomes.ContigSet or KBaseGenomeAnnotations.Assembly.),
+ parameter "files" of list of type "FASTAFile" (A local FASTA file.
+ path - the path to the FASTA file. label - the label to use for
+ the file in the QUAST output. If missing, the file name will be
+ used.) -> structure: parameter "path" of String, parameter "label"
+ of String, parameter "make_handle" of type "boolean" (A boolean -
+ 0 for false, 1 for true. @range (0, 1)), parameter "force_glimmer"
+ of type "boolean" (A boolean - 0 for false, 1 for true. @range (0,
+ 1)), parameter "min_contig_length" of Long
:returns: instance of type "QUASTOutput" (Ouput of the run_quast
function. shock_id - the id of the shock node where the zipped
QUAST output is stored. handle - the new handle for the shock
diff --git a/test/kb_quast_server_test.py b/test/kb_quast_server_test.py
index fd8ffd9..cbf3ce2 100644
--- a/test/kb_quast_server_test.py
+++ b/test/kb_quast_server_test.py
@@ -138,7 +138,7 @@ def test_quast_from_1_file(self):
ret = self.impl.run_QUAST(self.ctx, {'files': [
{'path': 'data/greengenes_UnAligSeq24606.fa', 'label': 'foobar'}],
'make_handle': 1})[0]
- self.check_quast_output(ret, 328982, 'a8ee2a3d96a3857105987c960185f307',
+ self.check_quast_output(ret, 329729, 'a64692fe665ba0174ca4992caa00ea77',
'6522bf4c7a54f96b99f7097c1a6afb01')
def test_quast_min_contig_length(self):
@@ -147,20 +147,20 @@ def test_quast_min_contig_length(self):
test_params = [
{
'min_contig_length': 50,
- 'expected_size': 329830,
- 'expected_report_md5': 'dbb67e35b015c4fbc41f0b2d06472de7',
+ 'expected_size': 330599,
+ 'expected_report_md5': '741b2d1dec8dbb81fe9a877c4bc1e329',
'expected_icarus_md5': '6522bf4c7a54f96b99f7097c1a6afb01'
},
{
'min_contig_length': 100,
- 'expected_size': 329868,
- 'expected_report_md5': '1ea996fa0d42cb950e7c59d7fa0207c2',
+ 'expected_size': 330656,
+ 'expected_report_md5': '354573cf4b70a013abb20e568aeae7f6',
'expected_icarus_md5': '6522bf4c7a54f96b99f7097c1a6afb01'
},
{
'min_contig_length': None,
- 'expected_size': 329068,
- 'expected_report_md5': '40a90e7a8a2f7cd527ddb9d46e6918d7',
+ 'expected_size': 329785,
+ 'expected_report_md5': '0812e658c08374fa26a1a93dd6b4402d',
'expected_icarus_md5': '6522bf4c7a54f96b99f7097c1a6afb01'
}
]
@@ -185,12 +185,12 @@ def test_quast_no_handle(self):
ret = self.impl.run_QUAST(self.ctx, {'files': [
{'path': 'data/greengenes_UnAligSeq24606.fa', 'label': 'foobar'}],
'make_handle': 0})[0]
- self.check_quast_output(ret, 328982, 'a8ee2a3d96a3857105987c960185f307',
+ self.check_quast_output(ret, 329726, 'a64692fe665ba0174ca4992caa00ea77',
'6522bf4c7a54f96b99f7097c1a6afb01', no_handle=True)
ret = self.impl.run_QUAST(self.ctx, {'files': [
{'path': 'data/greengenes_UnAligSeq24606.fa', 'label': 'foobar'}]})[0]
- self.check_quast_output(ret, 328982, 'a8ee2a3d96a3857105987c960185f307',
+ self.check_quast_output(ret, 329727, 'a64692fe665ba0174ca4992caa00ea77',
'6522bf4c7a54f96b99f7097c1a6afb01', no_handle=True)
def test_quast_from_2_files(self):
@@ -199,7 +199,7 @@ def test_quast_from_2_files(self):
{'path': 'data/greengenes_UnAligSeq24606.fa', 'label': 'foo'},
{'path': 'data/greengenes_UnAligSeq24606_edit1.fa'}],
'make_handle': 1})[0]
- self.check_quast_output(ret, 349008, '365aa50eda257a514b7fbae4edfba0a7',
+ self.check_quast_output(ret, 350263, 'd993842bcd881592aad50a8df8925499',
'2d10706f4ecfdbbe6d5d86e8578adbfa')
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -211,7 +211,7 @@ def test_quast_large_file(self):
{'path': 'data/greengenes_UnAligSeq24606_edit1.fa'}],
'make_handle': 1})[0]
- self.check_quast_output(ret, 345047, 'e8c7d24f35a8c3feb1da4c58623ad277',
+ self.check_quast_output(ret, 346400, '6aebc5fd90156d8ce31c64f30e19fa19',
'2d10706f4ecfdbbe6d5d86e8578adbfa', skip_glimmer=True)
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -222,7 +222,7 @@ def test_quast_large_file_force_glimmer(self):
{'path': 'data/greengenes_UnAligSeq24606_edit1.fa'}],
'make_handle': 1,
'force_glimmer': True})[0]
- self.check_quast_output(ret, 349007, '365aa50eda257a514b7fbae4edfba0a7',
+ self.check_quast_output(ret, 350266, 'd993842bcd881592aad50a8df8925499',
'2d10706f4ecfdbbe6d5d86e8578adbfa', skip_glimmer=False)
def test_quast_from_1_wsobj(self):
@@ -235,7 +235,7 @@ def test_quast_from_1_wsobj(self):
'workspace_name': self.ws_info[1],
'assembly_name': 'assy1'})
ret = self.impl.run_QUAST(self.ctx, {'assemblies': [ref], 'make_handle': 1})[0]
- self.check_quast_output(ret, 328484, 'f8a8b01c9939614b50381d9a760c3ee4',
+ self.check_quast_output(ret, 329244, '3e22e7ae2b33559a4f9bb18dc4f2b06c',
'140133e21ce35277cb7adc2eed2b1fd5')
def test_quast_from_2_wsobj(self):
@@ -263,7 +263,7 @@ def test_quast_from_2_wsobj(self):
ret = self.impl.run_QUAST(self.ctx, {'assemblies': [wsref1, wsref2], 'make_handle': 1})[0]
self.check_quast_output(
- ret, 343977, 'a44837b572fd48e6cd4179399b9aacd7', '3e2d94fb1d29d48c3058f8cbb68674ae',
+ ret, 345199, '8f9c1e7536cc3f94e4b00c2dd543e56f', '3e2d94fb1d29d48c3058f8cbb68674ae',
tolerance=30)
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -277,7 +277,7 @@ def test_quast_from_1_large_wsobj(self):
'workspace_name': self.ws_info[1],
'assembly_name': 'assy1'})
ret = self.impl.run_QUAST(self.ctx, {'assemblies': [ref], 'make_handle': 1})[0]
- self.check_quast_output(ret, 326214, '26876f8e773af163cf0e2518bbd28ab7',
+ self.check_quast_output(ret, 327029, '215bb5b5ae200c680e36d32813246b99',
'140133e21ce35277cb7adc2eed2b1fd5', skip_glimmer=True)
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -292,7 +292,7 @@ def test_quast_from_1_large_wsobj_force_glimmer(self):
'assembly_name': 'assy1'})
ret = self.impl.run_QUAST(self.ctx, {'assemblies': [ref], 'make_handle': 1,
'force_glimmer': True})[0]
- self.check_quast_output(ret, 328482, 'f8a8b01c9939614b50381d9a760c3ee4',
+ self.check_quast_output(ret, 329245, '3e22e7ae2b33559a4f9bb18dc4f2b06c',
'140133e21ce35277cb7adc2eed2b1fd5', skip_glimmer=False)
def test_fail_no_input(self):
@@ -404,7 +404,7 @@ def test_quast_app(self):
'assembly_name': 'assy1'})
ret = self.impl.run_QUAST_app(self.ctx, {'assemblies': [ref],
'workspace_name': self.ws_info[1]})[0]
- self.check_quast_app_output(ret, 328483, 'f8a8b01c9939614b50381d9a760c3ee4',
+ self.check_quast_app_output(ret, 329245, '3e22e7ae2b33559a4f9bb18dc4f2b06c',
'140133e21ce35277cb7adc2eed2b1fd5')
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -419,7 +419,7 @@ def test_quast_app_large_object(self):
'assembly_name': 'assy1'})
ret = self.impl.run_QUAST_app(self.ctx, {'assemblies': [ref],
'workspace_name': self.ws_info[1]})[0]
- self.check_quast_app_output(ret, 326214, '26876f8e773af163cf0e2518bbd28ab7',
+ self.check_quast_app_output(ret, 327027, '215bb5b5ae200c680e36d32813246b99',
'140133e21ce35277cb7adc2eed2b1fd5', skip_glimmer=True)
@patch.object(kb_quast, "TWENTY_MB", new=10)
@@ -435,7 +435,7 @@ def test_quast_app_large_object_force_glimmer(self):
ret = self.impl.run_QUAST_app(self.ctx, {'assemblies': [ref],
'workspace_name': self.ws_info[1],
'force_glimmer': True})[0]
- self.check_quast_app_output(ret, 328482, 'f8a8b01c9939614b50381d9a760c3ee4',
+ self.check_quast_app_output(ret, 329246, '3e22e7ae2b33559a4f9bb18dc4f2b06c',
'140133e21ce35277cb7adc2eed2b1fd5', skip_glimmer=False)
def test_fail_app_no_workspace(self):
diff --git a/ui/narrative/methods/run_QUAST_app/display.yaml b/ui/narrative/methods/run_QUAST_app/display.yaml
index 208e5af..adbfa66 100644
--- a/ui/narrative/methods/run_QUAST_app/display.yaml
+++ b/ui/narrative/methods/run_QUAST_app/display.yaml
@@ -1,4 +1,4 @@
-name : Assess Quality of Assemblies with QUAST - v4.4
+name : Assess Quality of Assemblies with QUAST - v5.2.0
tooltip : Run QUAST (QUality ASsessment Tool) on a set of Assemblies to assess their quality.
@@ -34,7 +34,7 @@ parameters :
Set the minimum size of contigs to process. Defaults to 500, minimum allowed is 50.
description : |
-
This is the KBase wrapper for version 4.4 of the QUAST assembly quality assessment tool. QUAST evaluates assemblies by computing various metrics, including number of contigs, N50/75, L50/75, GC content, number of uncalled bases (N’s), and predicted genes. It takes one or more Assembly objects as input and then generates an output report with statistics for all of the input assemblies.
+
This is the KBase wrapper for version 5.2.0 of the QUAST assembly quality assessment tool. QUAST evaluates assemblies by computing various metrics, including number of contigs, N50/75, L50/75, GC content, number of uncalled bases (N’s), and predicted genes. It takes one or more Assembly objects as input and then generates an output report with statistics for all of the input assemblies.
Use QUAST to assess the output assemblies from different configurations of the same assembler, or compare assemblies from multiple assemblers to determine which one is optimal for downstream analysis. The QUAST report color codes "worst, median, best" for each of the statistics generated, but pay attention to the degree of difference between the lengths and values to better understand how the parameters of your assembler relate to the resulting Assembly.