From 66265df1966b64081279050f2db91f24aedd81e2 Mon Sep 17 00:00:00 2001
From: Antonio Gonzalez
Date: Fri, 16 Jun 2017 10:37:42 -0600
Subject: [PATCH 01/18] nose-timer to pip command
---
.travis.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index d733d36cd..65d0d7086 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,11 +23,11 @@ install:
# install a few of the dependencies that pip would otherwise try to install
# when intalling scikit-bio
- travis_retry conda create --yes -n qiita python=$PYTHON_VERSION pip nose flake8
- pyzmq networkx pyparsing natsort mock future libgfortran seaborn nose-timer
+ pyzmq networkx pyparsing natsort mock future libgfortran seaborn
'pandas>=0.18' 'matplotlib>=1.1.0' 'scipy>0.13.0' 'numpy>=1.7' 'h5py>=2.3.1'
- source activate qiita
- pip install -U pip
- - pip install sphinx sphinx-bootstrap-theme coveralls 'ipython[all]==2.4.1'
+ - pip install sphinx sphinx-bootstrap-theme coveralls 'ipython[all]==2.4.1' nose-timer
- travis_retry pip install . --process-dependency-links
- 'echo "backend: Agg" > matplotlibrc'
# Install the biom plugin so we can run the analysis tests
From 304e2e457bc1fcaf68abd81ed845c913ac412abc Mon Sep 17 00:00:00 2001
From: Antonio Gonzalez
Date: Sun, 18 Jun 2017 06:20:37 -0600
Subject: [PATCH 02/18] improving study listing // artifact info
---
qiita_db/artifact.py | 68 +++++++
qiita_db/test/test_artifact.py | 31 ++++
qiita_db/test/test_util.py | 49 +----
qiita_db/util.py | 173 +-----------------
qiita_pet/handlers/api_proxy/__init__.py | 5 +-
qiita_pet/handlers/api_proxy/artifact.py | 39 ++++
.../handlers/api_proxy/tests/test_artifact.py | 43 ++++-
qiita_pet/handlers/study_handlers/__init__.py | 4 +-
qiita_pet/handlers/study_handlers/artifact.py | 12 +-
.../study_handlers/tests/test_artifact.py | 29 ++-
.../tests/test_listing_handlers.py | 26 +--
qiita_pet/static/css/style.css | 14 +-
qiita_pet/templates/list_studies.html | 137 ++++++++------
qiita_pet/webserver.py | 7 +-
14 files changed, 330 insertions(+), 307 deletions(-)
diff --git a/qiita_db/artifact.py b/qiita_db/artifact.py
index 3113a4bd7..9a3d0ac03 100644
--- a/qiita_db/artifact.py
+++ b/qiita_db/artifact.py
@@ -1181,6 +1181,74 @@ def analysis(self):
res = qdb.sql_connection.TRN.execute_fetchindex()
return qdb.analysis.Analysis(res[0][0]) if res else None
+ @property
+ def biom_info(self):
+ """Returns processing information about the bioms in the artifact
+
+ Returns
+ -------
+ dict or None
+ The info of the bioms if artifact_type is BIOM or None if not.
+ """
+ if self.artifact_type != 'BIOM':
+ return None
+ files = [(fid, fp)for fid, fp, fpt in self.filepaths if fpt == 'biom']
+ if not files:
+ return None
+
+ parameters = {}
+ with qdb.sql_connection.TRN:
+ # getting target_subfragment
+ sql = """
+ SELECT DISTINCT target_subfragment
+ FROM qiita.prep_%s
+ WHERE EXISTS (SELECT 1
+ FROM information_schema.columns
+ WHERE table_name='prep_%s'
+ AND column_name='target_subfragment')"""
+ pt_ids = [[pt.id, pt.id] for pt in self.prep_templates]
+ qdb.sql_connection.TRN.add(sql, pt_ids, many=True)
+ target_subfragment = qdb.sql_connection.TRN.execute_fetchflatten()
+
+ # getting processing_parameters
+ pp = self.processing_parameters
+ if pp is not None:
+ parameters = pp.values
+ parents = self.parents
+ if bool(parents):
+ # [0] an artifact can only have one processing parent
+ parent = parents[0]
+ ppp = parent.processing_parameters.command.name
+ # obtaining all processing parameters so we can then
+ # match, the parents processing params
+ sql_params = """
+ SELECT parameter_set_name, array_agg(ps) AS param_set
+ FROM qiita.default_parameter_set,
+ json_each_text(parameter_set) ps
+ GROUP BY parameter_set_name"""
+ qdb.sql_connection.TRN.add(sql_params)
+ params = {pname: eval(params) for pname, params
+ in qdb.sql_connection.TRN.execute_fetchindex()}
+ tpppv = {'(%s,%s)' % (k, v)
+ for k, v in viewitems(
+ parent.processing_parameters.values)}
+ pppv = sorted([
+ [k, len(tpppv & v)] for k, v in viewitems(params)],
+ key=lambda x: x[1])[-1][0]
+ else:
+ ppp = ''
+ pppv = ''
+
+ algorithm = '%s | %s (%s)' % (
+ pp.command.name, ppp, pppv)
+ else:
+ algorithm = 'N/A'
+
+ return {'target_subfragment': target_subfragment, 'name': self.name,
+ 'data_type': self.data_type, 'timestamp': self.timestamp,
+ 'parameters': parameters, 'algorithm': algorithm,
+ 'files': files}
+
def jobs(self, cmd=None, status=None):
"""Jobs that used this artifact as input
diff --git a/qiita_db/test/test_artifact.py b/qiita_db/test/test_artifact.py
index 0f51c498c..6d3f29767 100644
--- a/qiita_db/test/test_artifact.py
+++ b/qiita_db/test/test_artifact.py
@@ -407,6 +407,37 @@ def test_analysis(self):
qdb.analysis.Analysis(1))
self.assertIsNone(qdb.artifact.Artifact(1).analysis)
+ def test_biom_info(self):
+ # testing not biom
+ self.assertIsNone(qdb.artifact.Artifact(1).biom_info)
+ self.assertIsNone(qdb.artifact.Artifact(2).biom_info)
+ # test no biom // empty analysis
+ self.assertIsNone(qdb.artifact.Artifact(7).biom_info)
+ # regular processed file
+ bdir = qdb.util.get_db_files_base_dir()
+ obs = qdb.artifact.Artifact(4).biom_info
+ exp = {
+ 'files': [(9, join(bdir, 'processed_data/1_study_1001_closed'
+ '_reference_otu_table.biom'))],
+ 'target_subfragment': ['V4'], 'parameters': {
+ 'reference': 1, 'similarity': 0.97, 'sortmerna_e_value': 1,
+ 'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
+ 'sortmerna_coverage': 0.97},
+ 'algorithm': (
+ 'Pick closed-reference OTUs | Split libraries FASTQ '
+ '(Defaults with reverse complement mapping file barcodes)'),
+ 'timestamp': datetime(2012, 10, 2, 17, 30),
+ 'data_type': '18S', 'name': 'BIOM'}
+ self.assertEqual(obs, exp)
+ # analysis
+ obs = qdb.artifact.Artifact(8).biom_info
+ exp = {
+ 'files': [(15, join(bdir, 'analysis/1_analysis_18S.biom'))],
+ 'target_subfragment': [], 'parameters': {}, 'algorithm': 'N/A',
+ 'timestamp': datetime(2017, 6, 16, 15, 28, 28, 943120),
+ 'data_type': '18S', 'name': 'noname'}
+ self.assertEqual(obs, exp)
+
def test_jobs(self):
obs = qdb.artifact.Artifact(1).jobs()
exp = [
diff --git a/qiita_db/test/test_util.py b/qiita_db/test/test_util.py
index 5e609d3ee..288689442 100644
--- a/qiita_db/test/test_util.py
+++ b/qiita_db/test/test_util.py
@@ -807,7 +807,6 @@ def test_generate_study_list(self):
'shared': [('shared@foo.bar', 'Shared')],
'pi': ('PI_dude@foo.bar', 'PIDude'),
'status': 'private',
- 'proc_data_info': [],
'publication_doi': ['10.100/123456', '10.100/7891011'],
'publication_pid': ['123456', '7891011'],
'study_abstract': (
@@ -832,7 +831,7 @@ def test_generate_study_list(self):
'ebi_submission_status': 'not submitted', 'publication_pid': [],
'study_abstract': 'Some abstract goes here',
'pi': ('lab_dude@foo.bar', 'LabDude'), 'status': 'sandbox',
- 'proc_data_info': [], 'study_tags': None, 'shared': [],
+ 'study_tags': None, 'shared': [],
'publication_doi': [], 'study_id': new_study.id,
'ebi_study_accession': None, 'study_title': 'test_study_1',
'number_samples_collected': 0}]
@@ -841,55 +840,9 @@ def test_generate_study_list(self):
qdb.artifact.Artifact(4).visibility = 'public'
exp_info[0]['status'] = 'public'
- exp_info[0]['proc_data_info'] = [
- {'data_type': '18S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 4, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Greengenes',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, u'sortmerna_coverage': 0.97,
- 'reference_version': '13_8'}},
- {'data_type': '18S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 5, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Greengenes',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': '13_8'}},
- {'data_type': '16S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 6, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Silva',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': 'test'}}]
obs_info = qdb.util.generate_study_list([1, 2, 3, 4], True)
self.assertEqual(obs_info, exp_info)
- exp_info[0]['proc_data_info'] = [
- {'data_type': '18S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 4, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Greengenes',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': '13_8'}},
- {'data_type': '18S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 5, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Greengenes',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': '13_8'}},
- {'data_type': '16S', 'name': 'BIOM',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 6, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': 'Silva',
- 'sortmerna_e_value': 1, u'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': 'test'}},
- {'processed_date': '2012-10-02 17:30:00', 'pid': 7, 'name': 'BIOM',
- 'data_type': '16S'}]
obs_info = qdb.util.generate_study_list([1, 2, 3, 4], False)
self.assertEqual(obs_info, exp_info)
diff --git a/qiita_db/util.py b/qiita_db/util.py
index 4fce2cdc7..bb1d974fb 100644
--- a/qiita_db/util.py
+++ b/qiita_db/util.py
@@ -1211,7 +1211,7 @@ def generate_study_list(study_ids, public_only=False):
- the total number of samples collected by counting sample_ids
(SELECT COUNT(sample_id) FROM qiita.study_sample
WHERE study_id=qiita.study.study_id)
- AS number_samples_collected,
+ AS number_samples_collected]
- all the BIOM artifact_ids sorted by artifact_id that belong to the study
(SELECT array_agg(artifact_id ORDER BY artifact_id)
FROM qiita.study_artifact
@@ -1219,60 +1219,6 @@ def generate_study_list(study_ids, public_only=False):
LEFT JOIN qiita.artifact_type USING (artifact_type_id)
WHERE artifact_type='BIOM' AND
study_id = qiita.study.study_id) AS artifact_biom_ids,
- - all the BIOM data_types sorted by artifact_id that belong to the study
- (SELECT array_agg(data_type ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.data_type USING (data_type_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_dts,
- - all the BIOM parameters sorted by artifact_id that belong to the study
- (SELECT array_agg(command_parameters ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id)
- AS artifact_biom_params,
- - all the BIOM command_ids sorted by artifact_id that belong to the study,
- (SELECT array_agg(command_id ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id)
- AS artifact_biom_cmd,
- - all the BIOM timestamps sorted by artifact_id that belong to the study
- (SELECT array_agg(generated_timestamp ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_ts,
- - all the BIOM names sorted by artifact_id that belong to the study
- (SELECT array_agg(name ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_name,
- - all the BIOM visibility sorted by artifact_id that belong to the study
- (SELECT array_agg(visibility ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- LEFT JOIN qiita.visibility USING (visibility_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_vis,
- - all the visibilities of all artifacts that belong to the study
- (SELECT array_agg(DISTINCT visibility)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- LEFT JOIN qiita.visibility USING (visibility_id)
- WHERE study_id = qiita.study.study_id)
- AS artifacts_visibility,
- all the publications that belong to the study
(SELECT array_agg((publication, is_doi)))
FROM qiita.study_publication
@@ -1304,53 +1250,6 @@ def generate_study_list(study_ids, public_only=False):
LEFT JOIN qiita.artifact_type USING (artifact_type_id)
WHERE artifact_type='BIOM' AND
study_id = qiita.study.study_id) AS artifact_biom_ids,
- (SELECT array_agg(data_type ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.data_type USING (data_type_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_dts,
- (SELECT array_agg(command_parameters ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id)
- AS artifact_biom_params,
- (SELECT array_agg(command_id ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id)
- AS artifact_biom_cmd,
- (SELECT array_agg(generated_timestamp ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_ts,
- (SELECT array_agg(name ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_name,
- (SELECT array_agg(visibility ORDER BY artifact_id)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- LEFT JOIN qiita.visibility USING (visibility_id)
- WHERE artifact_type='BIOM' AND
- study_id = qiita.study.study_id) AS artifact_biom_vis,
- (SELECT array_agg(DISTINCT visibility)
- FROM qiita.study_artifact
- LEFT JOIN qiita.artifact USING (artifact_id)
- LEFT JOIN qiita.artifact_type USING (artifact_type_id)
- LEFT JOIN qiita.visibility USING (visibility_id)
- WHERE study_id = qiita.study.study_id)
- AS artifacts_visibility,
(SELECT array_agg(row_to_json((publication, is_doi), true))
FROM qiita.study_publication
WHERE study_id=qiita.study.study_id) AS publications,
@@ -1368,8 +1267,6 @@ def generate_study_list(study_ids, public_only=False):
WHERE study_id IN %s ORDER BY study_id"""
qdb.sql_connection.TRN.add(sql, [tuple(study_ids)])
infolist = []
- refs = {}
- commands = {}
for info in qdb.sql_connection.TRN.execute_fetchindex():
info = dict(info)
@@ -1387,12 +1284,6 @@ def generate_study_list(study_ids, public_only=False):
info['publication_pid'].append(pub)
del info['publications']
- # visibility
- # infer_status expects a list of list of str
- iav = info['artifacts_visibility']
- del info['artifacts_visibility']
- info["status"] = infer_status([[s] for s in iav] if iav else [])
-
# pi info
info["pi"] = (info['pi_email'], info['pi_name'])
del info["pi_email"]
@@ -1409,76 +1300,20 @@ def generate_study_list(study_ids, public_only=False):
del info["shared_with_name"]
del info["shared_with_email"]
- info['proc_data_info'] = []
- if info['artifact_biom_ids']:
- to_loop = zip(
- info['artifact_biom_ids'], info['artifact_biom_dts'],
- info['artifact_biom_ts'], info['artifact_biom_params'],
- info['artifact_biom_cmd'], info['artifact_biom_vis'],
- info['artifact_biom_name'])
- for artifact_id, dt, ts, params, cmd, vis, name in to_loop:
- if public_only and vis != 'public':
- continue
- proc_info = {'processed_date': str(ts)}
- proc_info['pid'] = artifact_id
- proc_info['data_type'] = dt
- proc_info['name'] = name
-
- # if cmd exists then we can get its parameters
- if cmd is not None:
- # making sure that the command is only queried once
- if cmd not in commands:
- c = qdb.software.Command(cmd)
- commands[cmd] = {
- # remove artifacts from parameters
- 'del_keys': [k for k, v in viewitems(
- c.parameters) if v[0] == 'artifact'],
- 'sfwn': c.software.name,
- 'sfv': c.software.version,
- 'cmdn': c.name
- }
- for k in commands[cmd]['del_keys']:
- del params[k]
-
- # making sure that the reference is only created once
- if 'reference' in params:
- rid = params.pop('reference')
- if rid not in refs:
- reference = qdb.reference.Reference(rid)
- tfp = basename(reference.taxonomy_fp)
- sfp = basename(reference.sequence_fp)
- refs[rid] = {
- 'name': reference.name,
- 'taxonomy_fp': tfp,
- 'sequence_fp': sfp,
- 'tree_fp': basename(reference.tree_fp),
- 'version': reference.version
- }
- params['reference_name'] = refs[rid]['name']
- params['reference_version'] = refs[rid][
- 'version']
-
- proc_info['algorithm'] = '%s v%s (%s)' % (
- commands[cmd]['sfwn'], commands[cmd]['sfv'],
- commands[cmd]['cmdn'])
- proc_info['params'] = params
-
- info["proc_data_info"].append(proc_info)
-
infolist.append({
'metadata_complete': info['metadata_complete'],
'publication_pid': info['publication_pid'],
'ebi_submission_status': info['ebi_submission_status'],
'shared': info['shared'],
'study_abstract': info['study_abstract'], 'pi': info['pi'],
- 'status': info['status'],
- 'proc_data_info': info['proc_data_info'],
+ 'status': qdb.study.Study(info['study_id']).status,
'study_tags': info['study_tags'],
'publication_doi': info['publication_doi'],
'study_id': info['study_id'],
'ebi_study_accession': info['ebi_study_accession'],
'study_title': info['study_title'],
- 'number_samples_collected': info['number_samples_collected']
+ 'number_samples_collected': info['number_samples_collected'],
+ 'artifact_biom_ids': info['artifact_biom_ids']
})
return infolist
diff --git a/qiita_pet/handlers/api_proxy/__init__.py b/qiita_pet/handlers/api_proxy/__init__.py
index 68a6956e1..514d4a759 100644
--- a/qiita_pet/handlers/api_proxy/__init__.py
+++ b/qiita_pet/handlers/api_proxy/__init__.py
@@ -32,7 +32,8 @@
artifact_post_req, artifact_get_req,
artifact_status_put_req, artifact_delete_req,
artifact_summary_get_request, artifact_get_prep_req,
- artifact_summary_post_request, artifact_patch_request)
+ artifact_summary_post_request, artifact_patch_request,
+ artifact_get_biom_info)
from .ontology import ontology_patch_handler
from .processing import (
list_commands_handler_get_req, process_artifact_handler_get_req,
@@ -54,7 +55,7 @@
'artifact_delete_req', 'prep_template_get_req', 'study_delete_req',
'study_prep_get_req', 'sample_template_get_req',
'artifact_graph_get_req', 'artifact_types_get_req',
- 'artifact_post_req',
+ 'artifact_post_req', 'artifact_get_biom_info',
'sample_template_meta_cats_get_req',
'sample_template_samples_get_req', 'prep_template_samples_get_req',
'sample_template_category_get_req', 'new_prep_template_get_req',
diff --git a/qiita_pet/handlers/api_proxy/artifact.py b/qiita_pet/handlers/api_proxy/artifact.py
index d6e04e6b3..ed0532446 100644
--- a/qiita_pet/handlers/api_proxy/artifact.py
+++ b/qiita_pet/handlers/api_proxy/artifact.py
@@ -296,6 +296,45 @@ def artifact_get_prep_req(user_id, artifact_ids):
return {'status': 'success', 'msg': '', 'data': samples}
+@execute_as_transaction
+def artifact_get_biom_info(user_id, artifact_ids):
+ """Returns all artifact info for the given artifact_ids
+
+ Parameters
+ ----------
+ user_id : str
+ user making the request
+ artifact_ids : list of int
+ list of artifact ids
+
+ Returns
+ -------
+ dict of objects
+ A dictionary containing the artifact information
+ {'status': status,
+ 'message': message,
+ 'data': {artifact_id: {biom_info}}
+ """
+ artifact_info = {}
+
+ for aid in artifact_ids:
+ artifact = Artifact(aid)
+ access_error = check_access(artifact.study.id, user_id)
+ if access_error:
+ return access_error
+
+ info = artifact.biom_info
+ if info is not None:
+ info['timestamp'] = str(info['timestamp'])
+ else:
+ # sending an empty string is better than sending None for web
+ # and testing
+ info = ''
+ artifact_info[aid] = info
+
+ return {'status': 'success', 'msg': '', 'data': artifact_info}
+
+
@execute_as_transaction
def artifact_post_req(user_id, filepaths, artifact_type, name,
prep_template_id, artifact_id=None):
diff --git a/qiita_pet/handlers/api_proxy/tests/test_artifact.py b/qiita_pet/handlers/api_proxy/tests/test_artifact.py
index 564bdd429..ce5d1a0b0 100644
--- a/qiita_pet/handlers/api_proxy/tests/test_artifact.py
+++ b/qiita_pet/handlers/api_proxy/tests/test_artifact.py
@@ -20,7 +20,7 @@
from qiita_db.artifact import Artifact
from qiita_db.metadata_template.prep_template import PrepTemplate
from qiita_db.study import Study
-from qiita_db.util import get_mountpoint
+from qiita_db.util import get_mountpoint, get_db_files_base_dir
from qiita_db.processing_job import ProcessingJob
from qiita_db.user import User
from qiita_db.software import Command, Parameters, DefaultParameters
@@ -29,7 +29,7 @@
artifact_get_req, artifact_status_put_req, artifact_graph_get_req,
artifact_delete_req, artifact_types_get_req, artifact_post_req,
artifact_summary_get_request, artifact_summary_post_request,
- artifact_patch_request, artifact_get_prep_req)
+ artifact_patch_request, artifact_get_prep_req, artifact_get_biom_info)
class TestArtifactAPIReadOnly(TestCase):
@@ -428,6 +428,45 @@ def test_artifact_get_prep_req(self):
'message': 'User does not have access to study'}
self.assertEqual(obs, exp)
+ def test_artifact_get_biom_info(self):
+ bdir = get_db_files_base_dir()
+
+ obs = artifact_get_biom_info('test@foo.bar', [5, 6])
+ exp = {'status': 'success', 'msg': '', 'data': {
+ 5: {'files': [(9, join(bdir, ('processed_data/1_study_1001_closed'
+ '_reference_otu_table.biom')))],
+ 'target_subfragment': ['V4'], 'parameters': {
+ 'reference': 1, 'similarity': 0.97, 'sortmerna_e_value': 1,
+ 'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
+ 'sortmerna_coverage': 0.97},
+ 'algorithm': ('Pick closed-reference OTUs | Split libraries '
+ 'FASTQ (Defaults with reverse complement '
+ 'mapping file barcodes)'),
+ 'timestamp': '2012-10-02 17:30:00',
+ 'data_type': '18S', 'name': 'BIOM'},
+ 6: {'files': [(12, join(bdir, (
+ 'processed_data/1_study_1001_closed_reference_otu_'
+ 'table_Silva.biom')))],
+ 'target_subfragment': ['V4'], 'parameters': {
+ 'reference': 2, 'similarity': 0.97, 'sortmerna_e_value': 1,
+ 'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
+ 'sortmerna_coverage': 0.97}, 'algorithm': (
+ 'Pick closed-reference OTUs | Split libraries FASTQ '
+ '(Defaults with reverse complement mapping file '
+ 'barcodes)'),
+ 'timestamp': '2012-10-02 17:30:00',
+ 'data_type': '16S', 'name': 'BIOM'}}}
+ self.assertEqual(obs, exp)
+
+ obs = artifact_get_biom_info('demo@microbio.me', [4])
+ exp = {'status': 'error',
+ 'message': 'User does not have access to study'}
+ self.assertEqual(obs, exp)
+
+ obs = artifact_get_biom_info('test@foo.bar', [7])
+ exp = {'status': 'success', 'msg': '', 'data': {7: ''}}
+ self.assertEqual(obs, exp)
+
def test_artifact_post_req(self):
# Create new prep template to attach artifact to
pt = npt.assert_warns(
diff --git a/qiita_pet/handlers/study_handlers/__init__.py b/qiita_pet/handlers/study_handlers/__init__.py
index 0cd6011d3..a635c403c 100644
--- a/qiita_pet/handlers/study_handlers/__init__.py
+++ b/qiita_pet/handlers/study_handlers/__init__.py
@@ -22,7 +22,7 @@
WorkflowRunHandler, JobAJAX)
from .artifact import (ArtifactGraphAJAX, NewArtifactHandler,
ArtifactAdminAJAX, ArtifactSummaryAJAX,
- ArtifactGetSamples)
+ ArtifactGetSamples, ArtifactGetBIOMInfo)
from .sample_template import SampleTemplateAJAX, SampleAJAX
__all__ = ['ListStudiesHandler', 'StudyApprovalList', 'ShareStudyAJAX',
@@ -36,4 +36,4 @@
'DataTypesMenuAJAX', 'StudyFilesAJAX', 'PrepTemplateSummaryAJAX',
'ArtifactSummaryAJAX', 'WorkflowHandler', 'WorkflowRunHandler',
'JobAJAX', 'AutocompleteHandler', 'StudyGetTags', 'StudyTags',
- 'ArtifactGetSamples']
+ 'ArtifactGetSamples', 'ArtifactGetBIOMInfo']
diff --git a/qiita_pet/handlers/study_handlers/artifact.py b/qiita_pet/handlers/study_handlers/artifact.py
index 9501c65fe..4884b2bed 100644
--- a/qiita_pet/handlers/study_handlers/artifact.py
+++ b/qiita_pet/handlers/study_handlers/artifact.py
@@ -16,7 +16,7 @@
artifact_graph_get_req, artifact_types_get_req, artifact_post_req,
artifact_status_put_req, artifact_get_req,
artifact_summary_get_request, artifact_summary_post_request,
- artifact_get_prep_req)
+ artifact_get_prep_req, artifact_get_biom_info)
from qiita_core.util import execute_as_transaction
from qiita_core.qiita_settings import qiita_config
@@ -87,6 +87,16 @@ def get(self):
self.write(response)
+class ArtifactGetBIOMInfo(BaseHandler):
+ @authenticated
+ def get(self):
+ aids = map(int, self.request.arguments.get('ids[]', []))
+
+ response = artifact_get_biom_info(self.current_user.id, aids)
+
+ self.write(response)
+
+
class ArtifactAdminAJAX(BaseHandler):
@authenticated
def get(self):
diff --git a/qiita_pet/handlers/study_handlers/tests/test_artifact.py b/qiita_pet/handlers/study_handlers/tests/test_artifact.py
index 880699d04..dc7a1e874 100644
--- a/qiita_pet/handlers/study_handlers/tests/test_artifact.py
+++ b/qiita_pet/handlers/study_handlers/tests/test_artifact.py
@@ -19,7 +19,7 @@
from qiita_pet.test.tornado_test_base import TestHandlerBase
from qiita_db.artifact import Artifact
from qiita_db.study import Study
-from qiita_db.util import get_mountpoint
+from qiita_db.util import get_mountpoint, get_db_files_base_dir
from qiita_db.metadata_template.prep_template import PrepTemplate
from qiita_db.exceptions import QiitaDBWarning
@@ -156,6 +156,33 @@ def test_get(self):
self.assertEqual(loads(response.body), exp)
+class ArtifactGetBIOMInfoTest(TestHandlerBase):
+ def test_get(self):
+ bdir = get_db_files_base_dir()
+
+ response = self.get('/artifact/info/', {'ids[]': [6, 7]})
+ self.assertEqual(response.code, 200)
+ exp = (
+ {'status': 'success', 'msg': '', 'data': {
+ '7': '',
+ '6': {
+ 'files': [[12, join(bdir, (
+ 'processed_data/1_study_1001_closed_reference_'
+ 'otu_table_Silva.biom'))]],
+ 'target_subfragment': ['V4'],
+ 'algorithm': ('Pick closed-reference OTUs | Split '
+ 'libraries FASTQ (Defaults with reverse '
+ 'complement mapping file barcodes)'),
+ 'data_type': '16S', 'timestamp': '2012-10-02 17:30:00',
+ 'parameters': {'reference': 2, 'similarity': 0.97,
+ 'sortmerna_e_value': 1,
+ 'sortmerna_max_pos': 10000,
+ 'input_data': 2, 'threads': 1,
+ 'sortmerna_coverage': 0.97},
+ 'name': 'BIOM'}}})
+ self.assertEqual(loads(response.body), exp)
+
+
class ArtifactAdminAJAXTestsReadOnly(TestHandlerBase):
def test_get_admin(self):
response = self.get('/admin/artifact/',
diff --git a/qiita_pet/handlers/study_handlers/tests/test_listing_handlers.py b/qiita_pet/handlers/study_handlers/tests/test_listing_handlers.py
index e4de44bb5..13ab0e0f2 100644
--- a/qiita_pet/handlers/study_handlers/tests/test_listing_handlers.py
+++ b/qiita_pet/handlers/study_handlers/tests/test_listing_handlers.py
@@ -24,25 +24,6 @@
GPARAMS = {'similarity': 0.97, 'reference_name': 'Greengenes',
'sortmerna_e_value': 1, 'sortmerna_max_pos': 10000, 'threads': 1,
'sortmerna_coverage': 0.97, 'reference_version': u'13_8'}
-PROC_DATA_INFO = [
- {'data_type': u'18S',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 4, 'processed_date': '2012-10-02 17:30:00', 'params': GPARAMS,
- 'name': 'BIOM'},
- {'data_type': '18S',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 5, 'processed_date': '2012-10-02 17:30:00', 'params': GPARAMS,
- 'name': 'BIOM'},
- {'data_type': '16S',
- 'algorithm': 'QIIME v1.9.1 (Pick closed-reference OTUs)',
- 'pid': 6, 'processed_date': '2012-10-02 17:30:00',
- 'params': {'similarity': 0.97, 'reference_name': u'Silva',
- 'sortmerna_e_value': 1, 'sortmerna_max_pos': 10000,
- 'threads': 1, 'sortmerna_coverage': 0.97,
- 'reference_version': 'test'},
- 'name': 'BIOM'},
- {'processed_date': '2012-10-02 17:30:00', 'pid': 7, 'data_type': '16S',
- 'name': 'BIOM'}]
class TestHelpers(TestHandlerBase):
@@ -74,8 +55,8 @@ def setUp(self):
'publication_doi': ['10.100/123456', '10.100/7891011'],
'publication_pid': ['123456', '7891011'],
'pi': ('PI_dude@foo.bar', 'PIDude'),
+ 'artifact_biom_ids': [4, 5, 6, 7],
'study_tags': None,
- 'proc_data_info': PROC_DATA_INFO
}
self.exp = [self.single_exp]
@@ -142,15 +123,14 @@ def test_build_study_info_empty_study(self):
'publication_pid': [],
'pi': ('PI_dude@foo.bar', 'PIDude'),
'status': 'sandbox',
- 'proc_data_info': [],
'publication_doi': [],
'study_abstract': 'abstract',
'study_id': 2,
'ebi_study_accession': None,
'study_title': 'My study',
'study_tags': None,
+ 'artifact_biom_ids': None,
'number_samples_collected': 0})
-
self.assertItemsEqual(obs, self.exp)
# Now testing that admin also sees this study
@@ -277,7 +257,6 @@ def setUp(self):
' (submitted)'),
'study_title': ('Identification of the Microbiomes for '
'Cannabis Soils'),
- 'proc_data_info': PROC_DATA_INFO,
'metadata_complete': True,
'ebi_submission_status': 'submitted',
'study_id': 1,
@@ -305,6 +284,7 @@ def setUp(self):
'Future studies will attempt to analyze the soils and '
'rhizospheres from the same location at different time '
'points in the plant lifecycle.'),
+ 'artifact_biom_ids': [4, 5, 6, 7],
'number_samples_collected': 27,
'study_tags': None}],
'sEcho': 1021,
diff --git a/qiita_pet/static/css/style.css b/qiita_pet/static/css/style.css
index db6cc183d..efb2e4b48 100644
--- a/qiita_pet/static/css/style.css
+++ b/qiita_pet/static/css/style.css
@@ -18,10 +18,18 @@
td.more-info-processing-jobs{
cursor: pointer;
- background: url('../img//details_open.png') no-repeat center center;
+ background: url('../img/details_open.png') no-repeat center center;
}
-tr.shown td.more-info-processing-jobs {
- background: url('../img//details_close.png') no-repeat center center;
+tr.shown td.more-info-processing-jobs{
+ background: url('../img/details_close.png') no-repeat center center;
+}
+
+td.details-control{
+ cursor: pointer;
+ background: url('../img/details_open.png') no-repeat center center;
+}
+tr.shown td.details-control{
+ background: url('../img/details_close.png') no-repeat center center;
}
.blinking-message {
diff --git a/qiita_pet/templates/list_studies.html b/qiita_pet/templates/list_studies.html
index d3a4de4ac..ca27433ca 100644
--- a/qiita_pet/templates/list_studies.html
+++ b/qiita_pet/templates/list_studies.html
@@ -35,9 +35,9 @@
var row_data = $('#'+name).dataTable().fnGetData(row);
var aids = []
- for(var i=0;i' +
- ' | ID | Name | Data type | Processed Date | ' +
- 'Algorithm | Parameters |
';
- for(i=0;i';
+ proc_data_table += ' | ';
+ proc_data_table += 'ID | ';
+ proc_data_table += 'Name | ';
+ proc_data_table += 'Data type | ';
+ proc_data_table += 'Target Subfragment | ';
+ proc_data_table += 'Processed Date | ';
+ proc_data_table += 'Algorithm | ';
+ proc_data_table += 'Parameters | ';
+ proc_data_table += 'Files | ';
+ proc_data_table += '';
+
+ $.each(data, function (pid, info) {
+ if (typeof info !== 'string' && !(info instanceof String)) {
+ proc_data_table += '';
+ proc_data_table += ' | ';
+ proc_data_table += '' + pid + ' | ';
+ proc_data_table += '' + info.name + ' | ';
+ proc_data_table += '' + info.data_type + ' | ';
+ proc_data_table += '' + info.target_subfragment.join(', ') + ' | ';
+ proc_data_table += '' + info.timestamp + ' | ';
+ proc_data_table += '' + info.algorithm + ' | ';
+
var params = '';
- var p = proc_data.params;
- for (var key in p) {
- params += '' + key + ': ' + p[key] + '
';
+ for (var key in info.parameters) {
+ params += '' + key + ': ' + info.parameters[key] + '
';
+ }
+ proc_data_table += '' + params + ' | ';
+
+ var files = '';
+ for (var key in info.files) {
+ var vals = info.files[key]
+ var name = vals[1].split('/');
+ files += 'FID: ' + vals[0];
+ files += '
';
+ files += 'Name: ' + name[name.length-1];
}
- proc_data_table += '
| ' +
- proc_data.pid + ' | ' + proc_data.name + ' | ' + proc_data.data_type + ' | ' +
- proc_data.processed_date + ' | ' +
- proc_data.algorithm + ' | ' + params + ' |
';
+ proc_data_table += '' + files + ' | ';
+
+ proc_data_table += '';
}
- proc_data_table += '';
- return proc_data_table;
+ });
+
+ proc_data_table += '';
+ return proc_data_table;
}
$('#user-studies-table').dataTable({
"lengthMenu": [[5, 10, 50, -1], [5, 10, 50, "All"]],
"deferRender": true,
"columns": [
- {"className": 'details-control', "orderable": false, "data": null, "defaultContent": ''},
+ {"className": 'details-control', "orderable": false, "data": null, "defaultContent": ''},
{ "orderable": false},
{ "data": "study_title" },
{ "data": "study_abstract" },
@@ -132,10 +157,11 @@
{"targets": [ 3 ], "visible": false},
// render the study checkbox cell
{"render": function ( data, type, row, meta ) {
- if(row.proc_data_info.length > 0) {
- return "";
- }
- else { return 'No Processed Data
'; }
+ return row.artifact_biom_ids.length
+ // if(row.proc_data_info.length > 0) {
+ // return "";
+ // }
+ // else { return 'No Processed Data
'; }
}, targets: [1]},
// render the title cell
{"render": function ( data, type, row, meta ) {
@@ -196,10 +222,10 @@
{"targets": [ 3 ], "visible": false},
// render the study checkbox cell
{"render": function ( data, type, row, meta ) {
- if(row.proc_data_info.length > 0) {
- return "";
- }
- else { return 'No Processed Data
'; }
+ // if(row.proc_data_info.length > 0) {
+ // return "";
+ // }
+ // else { return 'No Processed Data
'; }
}, targets: [1]},
// render the title cell
{"render": function ( data, type, row, meta ) {
@@ -239,15 +265,13 @@
var table = $('#studies-table').DataTable();
var tr = $(this).closest('tr');
var row = table.row( tr );
-
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
- }
- else {
+ } else {
// Open this row
- row.child( format('studies-table', row.data(), row.index()) ).show();
+ row.child( format_biom_rows('studies-table', row.data(), row.index()) ).show();
tr.addClass('shown');
}
});
@@ -255,16 +279,23 @@
var table = $('#user-studies-table').DataTable();
var tr = $(this).closest('tr');
var row = table.row( tr );
-
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
- }
- else {
+ } else {
// Open this row
- row.child( format('user-studies-table', row.data(), row.index()) ).show();
+ // modified from: https://jsfiddle.net/8rejaL88/2/
tr.addClass('shown');
+ row.child('
', 'no-padding' ).show();
+ $.get('/artifact/info/', {ids: row.data().artifact_biom_ids})
+ .done(function ( data ) {
+ if (data['status']=='success') {
+ $('td', row.child()).html(format_biom_rows('studies-table', data.data, row.index())).show();
+ } else {
+ bootstrapAlert('ERROR: ' + data['msg'], "danger", 10000);
+ }
+ });
}
});
@@ -376,7 +407,7 @@ Your Studies (includes shared with you)
- Expand |
+ For analysis |
Add to analysis |
Title |
Abstract |
@@ -392,19 +423,19 @@ Your Studies (includes shared with you)
Other Studies
-
-
- Expand |
- Add to analysis |
- Title |
- Abstract |
- Study ID |
- Samples |
- Principal Investigator |
- Publications |
- EBI |
-
-
+
+
+ For analysis |
+ Add to analysis |
+ Title |
+ Abstract |
+ Study ID |
+ Samples |
+ Principal Investigator |
+ Publications |
+ EBI |
+
+
diff --git a/qiita_pet/webserver.py b/qiita_pet/webserver.py
index ca3184691..9a8a6d3fe 100644
--- a/qiita_pet/webserver.py
+++ b/qiita_pet/webserver.py
@@ -30,8 +30,8 @@
ListCommandsHandler, ListOptionsHandler, PrepTemplateSummaryAJAX,
PrepTemplateAJAX, NewArtifactHandler, SampleAJAX, StudyDeleteAjax,
ArtifactAdminAJAX, NewPrepTemplateAjax, DataTypesMenuAJAX, StudyFilesAJAX,
- ArtifactGetSamples, WorkflowHandler, WorkflowRunHandler, JobAJAX,
- AutocompleteHandler)
+ ArtifactGetSamples, ArtifactGetBIOMInfo, WorkflowHandler,
+ WorkflowRunHandler, JobAJAX, AutocompleteHandler)
from qiita_pet.handlers.artifact_handlers import (
ArtifactSummaryAJAX, ArtifactAJAX, ArtifactSummaryHandler,
ProcessArtifactHandler)
@@ -106,12 +106,13 @@ def __init__(self):
(r"/analysis/description/(.*)/graph/", AnalysisGraphHandler),
(r"/analysis/description/(.*)/jobs/", AnalysisJobsHandler),
(r"/analysis/description/(.*)/", AnalysisDescriptionHandler),
+ (r"/artifact/samples/", ArtifactGetSamples),
+ (r"/artifact/info/", ArtifactGetBIOMInfo),
(r"/moi-ws/", MOIMessageHandler),
(r"/consumer/", MessageHandler),
(r"/admin/error/", LogEntryViewerHandler),
(r"/admin/approval/", StudyApprovalList),
(r"/admin/artifact/", ArtifactAdminAJAX),
- (r"/artifact/samples/", ArtifactGetSamples),
(r"/ebi_submission/(.*)", EBISubmitHandler),
# Study handlers
(r"/study/create/", StudyEditHandler),
From c97c34a82fe08682bb176e0cfc56fe37f6d54237 Mon Sep 17 00:00:00 2001
From: Antonio Gonzalez
Date: Sun, 18 Jun 2017 06:28:59 -0600
Subject: [PATCH 03/18] adding code to both list
---
qiita_pet/templates/list_studies.html | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/qiita_pet/templates/list_studies.html b/qiita_pet/templates/list_studies.html
index ca27433ca..eb6394823 100644
--- a/qiita_pet/templates/list_studies.html
+++ b/qiita_pet/templates/list_studies.html
@@ -87,7 +87,7 @@
$("#search-waiting").hide();
moi.init(null, window.location.host + '{% raw qiita_config.portal_dir %}/study/list/socket/', function(){}, error, error);
moi.add_callback('sel', show_alert);
- function format_biom_rows(name, data, row) {
+ function format_biom_rows(data, row) {
var proc_data_table = '';
proc_data_table += '';
proc_data_table += ' | ';
@@ -265,14 +265,24 @@
var table = $('#studies-table').DataTable();
var tr = $(this).closest('tr');
var row = table.row( tr );
+
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
} else {
// Open this row
- row.child( format_biom_rows('studies-table', row.data(), row.index()) ).show();
+ // modified from: https://jsfiddle.net/8rejaL88/2/
tr.addClass('shown');
+ row.child('
', 'no-padding' ).show();
+ $.get('/artifact/info/', {ids: row.data().artifact_biom_ids})
+ .done(function ( data ) {
+ if (data['status']=='success') {
+ $('td', row.child()).html(format_biom_rows(data.data, row.index())).show();
+ } else {
+ bootstrapAlert('ERROR: ' + data['msg'], "danger", 10000);
+ }
+ });
}
});
$('#user-studies-table tbody').on('click', 'td.details-control', function () {
@@ -291,7 +301,7 @@
$.get('/artifact/info/', {ids: row.data().artifact_biom_ids})
.done(function ( data ) {
if (data['status']=='success') {
- $('td', row.child()).html(format_biom_rows('studies-table', data.data, row.index())).show();
+ $('td', row.child()).html(format_biom_rows(data.data, row.index())).show();
} else {
bootstrapAlert('ERROR: ' + data['msg'], "danger", 10000);
}
From 82d9798b41940b9e2a302ff1aa3ac057051c35ef Mon Sep 17 00:00:00 2001
From: Antonio Gonzalez
Date: Sun, 18 Jun 2017 07:50:02 -0600
Subject: [PATCH 04/18] fix js length
---
qiita_pet/templates/list_studies.html | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/qiita_pet/templates/list_studies.html b/qiita_pet/templates/list_studies.html
index eb6394823..ca85a96d3 100644
--- a/qiita_pet/templates/list_studies.html
+++ b/qiita_pet/templates/list_studies.html
@@ -157,7 +157,11 @@
{"targets": [ 3 ], "visible": false},
// render the study checkbox cell
{"render": function ( data, type, row, meta ) {
- return row.artifact_biom_ids.length
+ var len = 0;
+ if (row.artifact_biom_ids != undefined) {
+ len = row.artifact_biom_ids.length;
+ }
+ return len
// if(row.proc_data_info.length > 0) {
// return "";
// }
@@ -207,7 +211,7 @@
"sDom": '<"top">rti<"bottom"p><"clear">',
"bLengthChange": false,
"columns": [
- {"className": 'details-control', "orderable": false, "data": null, "defaultContent": ''},
+ {"className": 'details-control', "orderable": false, "data": null, "defaultContent": ''},
{ "orderable": false},
{ "data": "study_title" },
{ "data": "study_abstract" },
@@ -222,8 +226,13 @@
{"targets": [ 3 ], "visible": false},
// render the study checkbox cell
{"render": function ( data, type, row, meta ) {
+ var len = 0;
+ if (row.artifact_biom_ids != undefined) {
+ len = row.artifact_biom_ids.length;
+ }
+ return len
// if(row.proc_data_info.length > 0) {
- // return "";
+ // return "";
// }
// else { return 'No Processed Data
'; }
}, targets: [1]},
From ddd724af4c2f45b535cadb063d899b2550dd2710 Mon Sep 17 00:00:00 2001
From: Antonio Gonzalez
Date: Tue, 20 Jun 2017 11:38:08 -0600
Subject: [PATCH 05/18] improving sql and display
---
qiita_db/artifact.py | 68 ---------
qiita_db/test/test_artifact.py | 31 ----
qiita_db/test/test_util.py | 26 ++++
qiita_db/util.py | 138 ++++++++++++++++++
qiita_pet/handlers/api_proxy/artifact.py | 18 +--
.../handlers/api_proxy/tests/test_artifact.py | 57 +++-----
qiita_pet/static/css/style.css | 41 ------
qiita_pet/static/js/qiita.js | 7 +-
qiita_pet/templates/list_studies.html | 17 +--
qiita_pet/templates/sitebase.html | 2 +-
10 files changed, 198 insertions(+), 207 deletions(-)
diff --git a/qiita_db/artifact.py b/qiita_db/artifact.py
index 9a3d0ac03..3113a4bd7 100644
--- a/qiita_db/artifact.py
+++ b/qiita_db/artifact.py
@@ -1181,74 +1181,6 @@ def analysis(self):
res = qdb.sql_connection.TRN.execute_fetchindex()
return qdb.analysis.Analysis(res[0][0]) if res else None
- @property
- def biom_info(self):
- """Returns processing information about the bioms in the artifact
-
- Returns
- -------
- dict or None
- The info of the bioms if artifact_type is BIOM or None if not.
- """
- if self.artifact_type != 'BIOM':
- return None
- files = [(fid, fp)for fid, fp, fpt in self.filepaths if fpt == 'biom']
- if not files:
- return None
-
- parameters = {}
- with qdb.sql_connection.TRN:
- # getting target_subfragment
- sql = """
- SELECT DISTINCT target_subfragment
- FROM qiita.prep_%s
- WHERE EXISTS (SELECT 1
- FROM information_schema.columns
- WHERE table_name='prep_%s'
- AND column_name='target_subfragment')"""
- pt_ids = [[pt.id, pt.id] for pt in self.prep_templates]
- qdb.sql_connection.TRN.add(sql, pt_ids, many=True)
- target_subfragment = qdb.sql_connection.TRN.execute_fetchflatten()
-
- # getting processing_parameters
- pp = self.processing_parameters
- if pp is not None:
- parameters = pp.values
- parents = self.parents
- if bool(parents):
- # [0] an artifact can only have one processing parent
- parent = parents[0]
- ppp = parent.processing_parameters.command.name
- # obtaining all processing parameters so we can then
- # match, the parents processing params
- sql_params = """
- SELECT parameter_set_name, array_agg(ps) AS param_set
- FROM qiita.default_parameter_set,
- json_each_text(parameter_set) ps
- GROUP BY parameter_set_name"""
- qdb.sql_connection.TRN.add(sql_params)
- params = {pname: eval(params) for pname, params
- in qdb.sql_connection.TRN.execute_fetchindex()}
- tpppv = {'(%s,%s)' % (k, v)
- for k, v in viewitems(
- parent.processing_parameters.values)}
- pppv = sorted([
- [k, len(tpppv & v)] for k, v in viewitems(params)],
- key=lambda x: x[1])[-1][0]
- else:
- ppp = ''
- pppv = ''
-
- algorithm = '%s | %s (%s)' % (
- pp.command.name, ppp, pppv)
- else:
- algorithm = 'N/A'
-
- return {'target_subfragment': target_subfragment, 'name': self.name,
- 'data_type': self.data_type, 'timestamp': self.timestamp,
- 'parameters': parameters, 'algorithm': algorithm,
- 'files': files}
-
def jobs(self, cmd=None, status=None):
"""Jobs that used this artifact as input
diff --git a/qiita_db/test/test_artifact.py b/qiita_db/test/test_artifact.py
index 6d3f29767..0f51c498c 100644
--- a/qiita_db/test/test_artifact.py
+++ b/qiita_db/test/test_artifact.py
@@ -407,37 +407,6 @@ def test_analysis(self):
qdb.analysis.Analysis(1))
self.assertIsNone(qdb.artifact.Artifact(1).analysis)
- def test_biom_info(self):
- # testing not biom
- self.assertIsNone(qdb.artifact.Artifact(1).biom_info)
- self.assertIsNone(qdb.artifact.Artifact(2).biom_info)
- # test no biom // empty analysis
- self.assertIsNone(qdb.artifact.Artifact(7).biom_info)
- # regular processed file
- bdir = qdb.util.get_db_files_base_dir()
- obs = qdb.artifact.Artifact(4).biom_info
- exp = {
- 'files': [(9, join(bdir, 'processed_data/1_study_1001_closed'
- '_reference_otu_table.biom'))],
- 'target_subfragment': ['V4'], 'parameters': {
- 'reference': 1, 'similarity': 0.97, 'sortmerna_e_value': 1,
- 'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
- 'sortmerna_coverage': 0.97},
- 'algorithm': (
- 'Pick closed-reference OTUs | Split libraries FASTQ '
- '(Defaults with reverse complement mapping file barcodes)'),
- 'timestamp': datetime(2012, 10, 2, 17, 30),
- 'data_type': '18S', 'name': 'BIOM'}
- self.assertEqual(obs, exp)
- # analysis
- obs = qdb.artifact.Artifact(8).biom_info
- exp = {
- 'files': [(15, join(bdir, 'analysis/1_analysis_18S.biom'))],
- 'target_subfragment': [], 'parameters': {}, 'algorithm': 'N/A',
- 'timestamp': datetime(2017, 6, 16, 15, 28, 28, 943120),
- 'data_type': '18S', 'name': 'noname'}
- self.assertEqual(obs, exp)
-
def test_jobs(self):
obs = qdb.artifact.Artifact(1).jobs()
exp = [
diff --git a/qiita_db/test/test_util.py b/qiita_db/test/test_util.py
index 288689442..27bc4e775 100644
--- a/qiita_db/test/test_util.py
+++ b/qiita_db/test/test_util.py
@@ -846,6 +846,32 @@ def test_generate_study_list(self):
obs_info = qdb.util.generate_study_list([1, 2, 3, 4], False)
self.assertEqual(obs_info, exp_info)
+ def test_get_artifacts_bioms_information(self):
+ # we are gonna test that it ignores 1 and 2 cause they are not biom,
+ # 4 has all information and 7 and 8 don't
+ obs = qdb.util.get_artifacts_bioms_information([1, 2, 4, 7, 8])
+ # not testing timestamp
+ for i in range(len(obs)):
+ del obs[i]['timestamp']
+ exp = [
+ {'files': ['1_study_1001_closed_reference_otu_table.biom'],
+ 'target_subfragment': ['V4'],
+ 'algorithm': 'Pick closed-reference OTUs, QIIMEv1.9.1 | Defaults',
+ 'artifact_id': 4, 'data_type': '18S',
+ 'parameters': {'reference': 1, 'similarity': 0.97,
+ 'sortmerna_e_value': 1, 'sortmerna_max_pos': 10000,
+ 'input_data': 2, 'threads': 1,
+ 'sortmerna_coverage': 0.97},
+ 'name': 'BIOM'}, {
+ 'files': [],
+ 'target_subfragment': ['V4'],
+ 'algorithm': '', 'artifact_id': 7, 'data_type': '16S',
+ 'parameters': {}, 'name': 'BIOM'},
+ {'files': ['1_analysis_18S.biom'], 'target_subfragment': [],
+ 'algorithm': '', 'artifact_id': 8, 'data_type': '18S',
+ 'parameters': {}, 'name': 'noname'}]
+ self.assertEqual(obs, exp)
+
if __name__ == '__main__':
main()
diff --git a/qiita_db/util.py b/qiita_db/util.py
index bb1d974fb..1b29c102b 100644
--- a/qiita_db/util.py
+++ b/qiita_db/util.py
@@ -1317,3 +1317,141 @@ def generate_study_list(study_ids, public_only=False):
})
return infolist
+
+
+def get_artifacts_bioms_information(artifact_ids):
+ """Returns processing information about the bioms in the artifact
+
+ Returns
+ -------
+ dict or None
+ The info of the bioms if artifact_type is BIOM or None if not.
+ """
+ sql = """
+ SELECT a.artifact_id, a.name, a.command_id, a.generated_timestamp,
+ array_agg(a.command_parameters), dt.data_type, parent_id,
+ array_agg(parent_info.command_parameters),
+ array_agg(filepaths.filepath), array_agg(pt.prep_id)
+ FROM qiita.artifact a
+ JOIN qiita.artifact_type at ON (
+ a.artifact_type_id = at .artifact_type_id
+ AND artifact_type = 'BIOM')
+ LEFT JOIN qiita.parent_artifact pa ON (
+ a.artifact_id = pa.artifact_id)
+ LEFT OUTER JOIN LATERAL (
+ SELECT command_parameters FROM qiita.artifact ap
+ WHERE ap.artifact_id = pa.parent_id) parent_info ON true
+ LEFT OUTER JOIN LATERAL (
+ SELECT filepath
+ FROM qiita.artifact_filepath af
+ JOIN qiita.filepath USING (filepath_id)
+ WHERE af.artifact_id = a.artifact_id) filepaths ON true
+ LEFT OUTER JOIN LATERAL (
+ SELECT data_type
+ FROM qiita.data_type
+ WHERE data_type_id = a.data_type_id) dt ON true
+ LEFT OUTER JOIN LATERAL (
+ SELECT CASE WHEN (
+ SELECT true
+ FROM information_schema.columns
+ WHERE table_name = 'prep_' || CAST(
+ prep_template_id AS TEXT)
+ AND column_name='target_subfragment')
+ THEN prep_template_id
+ ELSE null END AS prep_id
+ FROM qiita.prep_template pt
+ WHERE pt.artifact_id IN (
+ SELECT * FROM qiita.find_artifact_roots(a.artifact_id)))
+ pt ON true
+ WHERE a.artifact_id IN %s
+ GROUP BY a.artifact_id, a.name, a.command_id,
+ a.generated_timestamp, dt.data_type, parent_id
+ ORDER BY command_id, artifact_id
+ """
+
+ sql_params = """
+ SELECT parameter_set_name, array_agg(parameter_set) AS param_set
+ FROM qiita.default_parameter_set
+ GROUP BY parameter_set_name"""
+
+ sql_ts = """SELECT DISTINCT target_subfragment FROM qiita.prep_%s"""
+
+ with qdb.sql_connection.TRN:
+ results = []
+ commands = {}
+ # obtaining all existing parameters, note that
+ # they are not that many (~40) and we don't expect
+ # to have a huge growth in the near future
+ qdb.sql_connection.TRN.add(sql_params)
+ params = {name: set(params[0].iteritems()) for name, params in
+ qdb.sql_connection.TRN.execute_fetchindex()}
+
+ # now let's get the actual artifacts
+ qdb.sql_connection.TRN.add(sql, [tuple(artifact_ids)])
+ for row in qdb.sql_connection.TRN.execute_fetchindex():
+ aid, name, cid, gt, aparams, dt, pid, pparams, filepaths, \
+ target = row
+ # cleaning fields:
+ # - [0] due to the array_agg
+ pparams = pparams[0]
+ if pparams is not None:
+ # [-1] taking the last cause it's sorted by
+ # the number of overlapping parameters
+ # [0] then taking the first element that is
+ # the name of the parameter set
+ pparams = sorted([
+ [k, len(v & set(pparams.iteritems()))]
+ for k, v in viewitems(params)],
+ key=lambda x: x[1])[-1][0]
+ else:
+ pparams = 'N/A'
+ # - [0] due to the array_agg
+ aparams = aparams[0]
+ if aparams is None:
+ aparams = {}
+ # - ignoring empty filepaths
+ if filepaths == [None]:
+ filepaths = []
+ # - ignoring empty target
+ if target == [None]:
+ target = []
+
+ algorithm = ''
+ if cid is not None:
+ if cid not in commands:
+ c = qdb.software.Command(cid)
+ s = c.software
+ commands[cid] = '%s, %sv%s' % (
+ c.name, s.name, s.version)
+
+ algorithm = '%s | %s' % (commands[cid], pparams)
+
+ results.append({
+ 'artifact_id': aid,
+ 'target_subfragment': target,
+ 'name': name,
+ 'data_type': dt,
+ 'timestamp': str(gt),
+ 'parameters': aparams,
+ 'algorithm': algorithm,
+ 'files': filepaths})
+
+ # let's get the values for target_subfragment from the
+ # prep_template, note that we have to do it in a separate sql
+ # doing crosstab is really difficult and in another loop cause we
+ # need to loop over all execute_fetchindex before doing another
+ # query
+ ts = {}
+ for i, r in enumerate(results):
+ ats = []
+ for pid in r['target_subfragment']:
+ if pid not in ts:
+ qdb.sql_connection.TRN.add(sql_ts, [pid])
+ ts[pid] = qdb.sql_connection.TRN.execute_fetchflatten()
+ ats.extend(ts[pid])
+
+ # set to remove any duplicates, then list so JSON can serialize
+ # and play nice with web
+ results[i]['target_subfragment'] = list(set(ats))
+
+ return results
diff --git a/qiita_pet/handlers/api_proxy/artifact.py b/qiita_pet/handlers/api_proxy/artifact.py
index ed0532446..0a668b0b9 100644
--- a/qiita_pet/handlers/api_proxy/artifact.py
+++ b/qiita_pet/handlers/api_proxy/artifact.py
@@ -21,7 +21,8 @@
from qiita_db.artifact import Artifact
from qiita_db.user import User
from qiita_db.metadata_template.prep_template import PrepTemplate
-from qiita_db.util import get_mountpoint, get_visibilities
+from qiita_db.util import (
+ get_mountpoint, get_visibilities, get_artifacts_bioms_information)
from qiita_db.software import Command, Parameters
from qiita_db.processing_job import ProcessingJob
@@ -317,20 +318,7 @@ def artifact_get_biom_info(user_id, artifact_ids):
"""
artifact_info = {}
- for aid in artifact_ids:
- artifact = Artifact(aid)
- access_error = check_access(artifact.study.id, user_id)
- if access_error:
- return access_error
-
- info = artifact.biom_info
- if info is not None:
- info['timestamp'] = str(info['timestamp'])
- else:
- # sending an empty string is better than sending None for web
- # and testing
- info = ''
- artifact_info[aid] = info
+ artifact_info = get_artifacts_bioms_information(artifact_ids)
return {'status': 'success', 'msg': '', 'data': artifact_info}
diff --git a/qiita_pet/handlers/api_proxy/tests/test_artifact.py b/qiita_pet/handlers/api_proxy/tests/test_artifact.py
index ce5d1a0b0..78d944902 100644
--- a/qiita_pet/handlers/api_proxy/tests/test_artifact.py
+++ b/qiita_pet/handlers/api_proxy/tests/test_artifact.py
@@ -429,42 +429,33 @@ def test_artifact_get_prep_req(self):
self.assertEqual(obs, exp)
def test_artifact_get_biom_info(self):
- bdir = get_db_files_base_dir()
-
- obs = artifact_get_biom_info('test@foo.bar', [5, 6])
- exp = {'status': 'success', 'msg': '', 'data': {
- 5: {'files': [(9, join(bdir, ('processed_data/1_study_1001_closed'
- '_reference_otu_table.biom')))],
- 'target_subfragment': ['V4'], 'parameters': {
+ obs = artifact_get_biom_info('test@foo.bar', [5, 6, 7])
+ exp = {
+ 'status': 'success', 'msg': '', 'data': [
+ {'files': ['1_study_1001_closed_reference_otu_table.biom'],
+ 'target_subfragment': ['V4'],
+ 'algorithm': ('Pick closed-reference OTUs, QIIMEv1.9.1'
+ ' | Defaults'), 'artifact_id': 5,
+ 'data_type': '18S', 'timestamp': '2012-10-02 17:30:00',
+ 'parameters': {
'reference': 1, 'similarity': 0.97, 'sortmerna_e_value': 1,
'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
'sortmerna_coverage': 0.97},
- 'algorithm': ('Pick closed-reference OTUs | Split libraries '
- 'FASTQ (Defaults with reverse complement '
- 'mapping file barcodes)'),
- 'timestamp': '2012-10-02 17:30:00',
- 'data_type': '18S', 'name': 'BIOM'},
- 6: {'files': [(12, join(bdir, (
- 'processed_data/1_study_1001_closed_reference_otu_'
- 'table_Silva.biom')))],
- 'target_subfragment': ['V4'], 'parameters': {
- 'reference': 2, 'similarity': 0.97, 'sortmerna_e_value': 1,
- 'sortmerna_max_pos': 10000, 'input_data': 2, 'threads': 1,
- 'sortmerna_coverage': 0.97}, 'algorithm': (
- 'Pick closed-reference OTUs | Split libraries FASTQ '
- '(Defaults with reverse complement mapping file '
- 'barcodes)'),
- 'timestamp': '2012-10-02 17:30:00',
- 'data_type': '16S', 'name': 'BIOM'}}}
- self.assertEqual(obs, exp)
-
- obs = artifact_get_biom_info('demo@microbio.me', [4])
- exp = {'status': 'error',
- 'message': 'User does not have access to study'}
- self.assertEqual(obs, exp)
-
- obs = artifact_get_biom_info('test@foo.bar', [7])
- exp = {'status': 'success', 'msg': '', 'data': {7: ''}}
+ 'name': 'BIOM'},
+ {'files': ['1_study_1001_closed_reference_otu_table_'
+ 'Silva.biom'], 'target_subfragment': ['V4'],
+ 'algorithm': ('Pick closed-reference OTUs, QIIMEv1.9.1'
+ ' | Defaults'), 'artifact_id': 6,
+ 'data_type': '16S', 'timestamp': '2012-10-02 17:30:00',
+ 'parameters': {'reference': 2, 'similarity': 0.97,
+ 'sortmerna_e_value': 1,
+ 'sortmerna_max_pos': 10000, 'input_data': 2,
+ 'threads': 1, 'sortmerna_coverage': 0.97},
+ 'name': 'BIOM'}, {
+ 'files': [], 'target_subfragment': ['V4'], 'algorithm': '',
+ 'artifact_id': 7, 'data_type': '16S',
+ 'timestamp': '2012-10-02 17:30:00', 'parameters': {},
+ 'name': 'BIOM'}]}
self.assertEqual(obs, exp)
def test_artifact_post_req(self):
diff --git a/qiita_pet/static/css/style.css b/qiita_pet/static/css/style.css
index efb2e4b48..a39f550d9 100644
--- a/qiita_pet/static/css/style.css
+++ b/qiita_pet/static/css/style.css
@@ -51,7 +51,6 @@ tr.shown td.details-control{
display: block;
}
-
.info-menu {
word-wrap: break-word;
white-space: normal;
@@ -84,43 +83,3 @@ tr.shown td.details-control{
height:300px;
border: 1px solid #ccc;
}
-
-/* Make the navbar collapse at medium size, not small.
-Fixes really ugly middle ground where menu stacking occurs
-adapted from http://stackoverflow.com/a/23298184 */
-@media (max-width: 991px) {
- .navbar-header {
- float: none;
- }
- .navbar-toggle {
- display: block;
- }
- .navbar-collapse {
- border-top: 1px solid transparent;
- box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
- }
- .navbar-collapse.collapse {
- display: none!important;
- }
- .navbar-nav {
- float: none!important;
- margin: 7.5px -15px;
- }
- .navbar-nav>li {
- float: none;
- }
- .navbar-nav>li>a {
- padding-top: 10px;
- padding-bottom: 10px;
- }
- .navbar-text {
- float: none;
- margin: 15px 0;
- }
- /* since 3.1.0 */ .navbar-collapse.collapse.in {
- display: block!important;
- }
- .collapsing {
- overflow: hidden!important;
- }
-}
diff --git a/qiita_pet/static/js/qiita.js b/qiita_pet/static/js/qiita.js
index 10b0d1657..77ff78d11 100644
--- a/qiita_pet/static/js/qiita.js
+++ b/qiita_pet/static/js/qiita.js
@@ -11,9 +11,6 @@
var timeoutHandleForBoostrapAlert = null;
function bootstrapAlert(message, severity, timeout){
- // Clear the previous alert - so they don't keep stacking on top of each other
- $('#bootstrap-alert').alert('close');
-
// make timeout an optional parameter
timeout = timeout || -1;
@@ -32,14 +29,14 @@ function bootstrapAlert(message, severity, timeout){
alertDiv.append('Need help? Send us an email.
');
}
- $('#qiita-main').prepend(alertDiv);
+ $('#template-content').prepend(alertDiv);
if(timeout > 0) {
if (timeoutHandleForBoostrapAlert != null) {
window.clearTimeout(timeoutHandleForBoostrapAlert);
}
timeoutHandleForBoostrapAlert = window.setTimeout(function() {
- $('#alert-message').alert('close');
+ $('#alert-message').remove();
timeoutHandleForBoostrapAlert = null;
}, timeout);
}
diff --git a/qiita_pet/templates/list_studies.html b/qiita_pet/templates/list_studies.html
index ca85a96d3..51fa695ef 100644
--- a/qiita_pet/templates/list_studies.html
+++ b/qiita_pet/templates/list_studies.html
@@ -101,11 +101,11 @@
proc_data_table += 'Files | ';
proc_data_table += '
';
- $.each(data, function (pid, info) {
+ $.each(data, function (idx, info) {
if (typeof info !== 'string' && !(info instanceof String)) {
proc_data_table += '';
- proc_data_table += ' | ';
- proc_data_table += '' + pid + ' | ';
+ proc_data_table += ' | ';
+ proc_data_table += '' + info.artifact_id + ' | ';
proc_data_table += '' + info.name + ' | ';
proc_data_table += '' + info.data_type + ' | ';
proc_data_table += '' + info.target_subfragment.join(', ') + ' | ';
@@ -117,16 +117,7 @@
params += '' + key + ': ' + info.parameters[key] + '
';
}
proc_data_table += '' + params + ' | ';
-
- var files = '';
- for (var key in info.files) {
- var vals = info.files[key]
- var name = vals[1].split('/');
- files += 'FID: ' + vals[0];
- files += '
';
- files += 'Name: ' + name[name.length-1];
- }
- proc_data_table += '' + files + ' | ';
+ proc_data_table += '' + info.files.join(', ') + ' | ';
proc_data_table += '
';
}
diff --git a/qiita_pet/templates/sitebase.html b/qiita_pet/templates/sitebase.html
index 17c7c819b..31409d7f8 100644
--- a/qiita_pet/templates/sitebase.html
+++ b/qiita_pet/templates/sitebase.html
@@ -362,7 +362,7 @@