diff --git a/qiita_db/test/test_util.py b/qiita_db/test/test_util.py index d4de09e4d..5af9576a4 100644 --- a/qiita_db/test/test_util.py +++ b/qiita_db/test/test_util.py @@ -801,98 +801,73 @@ def test_generate_study_list(self): qdb.user.User('shared@foo.bar'), 'test_study_1', efo=[1], info=info) - exp_info = [{ - 'metadata_complete': True, - 'ebi_submission_status': 'submitted', - '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': ( + exp_info = [ + {'status': 'private', 'metadata_complete': True, + 'study_tags': None, 'publication_doi': [ + '10.100/123456', '10.100/7891011'], + 'study_title': ('Identification of the Microbiomes for ' + 'Cannabis Soils'), + 'publication_pid': ['123456', '7891011'], + 'ebi_submission_status': 'submitted', 'study_id': 1, + 'ebi_study_accession': 'EBI123456-BB', + 'shared': [('shared@foo.bar', 'Shared')], + 'study_abstract': ( 'This is a preliminary study to examine the microbiota ' - 'associated with the Cannabis plant. Soils samples from ' - 'the bulk soil, soil associated with the roots, and the ' - 'rhizosphere were extracted and the DNA sequenced. Roots ' - 'from three independent plants of different strains were ' - 'examined. These roots were obtained November 11, 2011 from ' - 'plants that had been harvested in the summer. Future studies ' - 'will attempt to analyze the soils and rhizospheres from the ' - 'same location at different time points in the plant ' - 'lifecycle.'), - 'study_id': 1, - 'ebi_study_accession': 'EBI123456-BB', - 'study_title': ('Identification of the Microbiomes for Cannabis ' - 'Soils'), - 'number_samples_collected': 27, - 'study_tags': None - }, { - 'metadata_complete': True, - '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': [], - 'publication_doi': [], 'study_id': new_study.id, - 'ebi_study_accession': None, 'study_title': 'test_study_1', - 'number_samples_collected': 0}] + 'associated with the Cannabis plant. Soils samples from the ' + 'bulk soil, soil associated with the roots, and the ' + 'rhizosphere were extracted and the DNA sequenced. Roots from ' + 'three independent plants of different strains were examined. ' + 'These roots were obtained November 11, 2011 from plants that ' + 'had been harvested in the summer. Future studies will ' + 'attempt to analyze the soils and rhizospheres from the same ' + 'location at different time points in the plant lifecycle.'), + 'pi': ('PI_dude@foo.bar', 'PIDude'), + 'artifact_biom_ids': [4, 5, 6, 7], + 'number_samples_collected': 27}, + {'status': 'sandbox', 'metadata_complete': True, + 'study_tags': None, 'publication_doi': [], + 'study_title': 'test_study_1', 'publication_pid': [], + 'ebi_submission_status': 'not submitted', + 'study_id': new_study.id, 'ebi_study_accession': None, + 'shared': [], 'study_abstract': 'Some abstract goes here', + 'pi': ('lab_dude@foo.bar', 'LabDude'), + 'artifact_biom_ids': None, 'number_samples_collected': 0}] obs_info = qdb.util.generate_study_list([1, 2, 3, 4], True) self.assertEqual(obs_info, exp_info) 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) + 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'], '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', + 'algorithm': ('Pick closed-reference OTUs, QIIMEv1.9.1 ' + '| barcode_type 8, defaults'), 'artifact_id': 4}, + {'files': [], 'target_subfragment': ['V4'], 'data_type': '16S', + 'parameters': {}, 'name': 'BIOM', 'algorithm': '', + 'artifact_id': 7}, + {'files': ['biom_table.biom'], 'target_subfragment': [], + 'data_type': '18S', 'parameters': {}, 'name': 'noname', + 'algorithm': '', 'artifact_id': 8}] + self.assertEqual(obs, exp) + if __name__ == '__main__': main() diff --git a/qiita_db/util.py b/qiita_db/util.py index 8288367a4..edb8c25c9 100644 --- a/qiita_db/util.py +++ b/qiita_db/util.py @@ -1215,7 +1215,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 @@ -1223,60 +1223,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 @@ -1308,53 +1254,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, @@ -1369,11 +1268,10 @@ def generate_study_list(study_ids, public_only=False): FROM qiita.study LEFT JOIN qiita.study_person ON ( study_person_id=principal_investigator_id) - WHERE study_id IN %s ORDER BY study_id""" + 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) @@ -1391,12 +1289,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"] @@ -1413,76 +1305,165 @@ 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 + + +def get_artifacts_bioms_information(artifact_ids): + """Returns processing information about the bioms in the artifact + + Parameters + ---------- + artifact_ids : list of ints + The artifact ids to look for. Non-existing ids will be ignored + + Returns + ------- + dict + The info of the bioms if artifact_type is BIOM or None if not. + """ + if not artifact_ids: + return {} + + sql = """ + WITH main_query AS ( + 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), + qiita.find_artifact_roots(a.artifact_id) AS root_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 JOIN qiita.data_type dt USING (data_type_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 + 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), + has_target_subfragment AS ( + SELECT main_query.*, 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 + FROM main_query + LEFT JOIN qiita.prep_template pt ON ( + main_query.root_id = pt.artifact_id) + ) + SELECT * FROM has_target_subfragment + ORDER BY command_id, data_type, 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): + pid = r['target_subfragment'] + if pid is None: + results[i]['target_subfragment'] = [] + else: + if pid not in ts: + qdb.sql_connection.TRN.add(sql_ts, [pid]) + ts[pid] = qdb.sql_connection.TRN.execute_fetchflatten() + results[i]['target_subfragment'] = ts[pid] + + return results diff --git a/qiita_pet/handlers/api_proxy/__init__.py b/qiita_pet/handlers/api_proxy/__init__.py index 9dee67bb5..294661c7a 100644 --- a/qiita_pet/handlers/api_proxy/__init__.py +++ b/qiita_pet/handlers/api_proxy/__init__.py @@ -31,7 +31,7 @@ from .artifact import (artifact_graph_get_req, artifact_types_get_req, artifact_post_req, artifact_get_req, artifact_status_put_req, artifact_get_prep_req, - artifact_patch_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, @@ -53,7 +53,7 @@ '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 2d8e10b51..6fe8c62ed 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 @@ -108,6 +109,32 @@ 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 = {} + + artifact_info = get_artifacts_bioms_information(artifact_ids) + + 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 a4e92cfff..15e774bf5 100644 --- a/qiita_pet/handlers/api_proxy/tests/test_artifact.py +++ b/qiita_pet/handlers/api_proxy/tests/test_artifact.py @@ -25,8 +25,8 @@ from qiita_db.exceptions import QiitaDBWarning from qiita_pet.handlers.api_proxy.artifact import ( artifact_get_req, artifact_status_put_req, artifact_graph_get_req, - artifact_types_get_req, artifact_post_req, - artifact_patch_request, artifact_get_prep_req) + artifact_types_get_req, artifact_post_req, artifact_patch_request, + artifact_get_prep_req, artifact_get_biom_info) class TestArtifactAPIReadOnly(TestCase): @@ -219,6 +219,32 @@ 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): + obs = artifact_get_biom_info('test@foo.bar', [5, 6, 7]) + data = [ + {'files': ['1_study_1001_closed_reference_otu_table_Silva.biom'], + 'target_subfragment': ['V4'], 'algorithm': ( + 'Pick closed-reference OTUs, QIIMEv1.9.1 | barcode_type 8, ' + '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': ['1_study_1001_closed_reference_otu_table.biom'], + 'target_subfragment': ['V4'], 'algorithm': ( + 'Pick closed-reference OTUs, QIIMEv1.9.1 | barcode_type 8, ' + '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}, 'name': 'BIOM'}, + {'files': [], 'target_subfragment': ['V4'], 'algorithm': '', + 'artifact_id': 7, 'data_type': '16S', + 'timestamp': '2012-10-02 17:30:00', 'parameters': {}, + 'name': 'BIOM'}] + exp = {'status': 'success', 'msg': '', 'data': data} + 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 ed7f47c4d..0832aebb2 100644 --- a/qiita_pet/handlers/study_handlers/__init__.py +++ b/qiita_pet/handlers/study_handlers/__init__.py @@ -21,7 +21,8 @@ ListOptionsHandler, WorkflowHandler, WorkflowRunHandler, JobAJAX) from .artifact import (ArtifactGraphAJAX, NewArtifactHandler, - ArtifactAdminAJAX, ArtifactGetSamples) + ArtifactAdminAJAX, ArtifactGetSamples, + ArtifactGetBIOMInfo) from .sample_template import SampleTemplateAJAX, SampleAJAX __all__ = ['ListStudiesHandler', 'StudyApprovalList', 'ShareStudyAJAX', @@ -35,4 +36,4 @@ 'DataTypesMenuAJAX', 'StudyFilesAJAX', 'PrepTemplateSummaryAJAX', '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 cae160e8c..4539c3a17 100644 --- a/qiita_pet/handlers/study_handlers/artifact.py +++ b/qiita_pet/handlers/study_handlers/artifact.py @@ -14,7 +14,8 @@ from qiita_pet.handlers.base_handlers import BaseHandler from qiita_pet.handlers.api_proxy import ( artifact_graph_get_req, artifact_types_get_req, artifact_post_req, - artifact_status_put_req, artifact_get_req, artifact_get_prep_req) + artifact_status_put_req, artifact_get_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 @@ -68,6 +69,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 b86ca2282..8cc26db63 100644 --- a/qiita_pet/handlers/study_handlers/tests/test_artifact.py +++ b/qiita_pet/handlers/study_handlers/tests/test_artifact.py @@ -158,6 +158,27 @@ def test_get(self): self.assertEqual(loads(response.body), exp) +class ArtifactGetBIOMInfoTest(TestHandlerBase): + def test_get(self): + response = self.get('/artifact/info/', {'ids[]': [6, 7]}) + self.assertEqual(response.code, 200) + data = [ + {'files': ['1_study_1001_closed_reference_otu_table_Silva.biom'], + 'target_subfragment': ['V4'], 'algorithm': ( + 'Pick closed-reference OTUs, QIIMEv1.9.1 | barcode_type 8, ' + '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'}] + exp = {'status': 'success', 'msg': '', 'data': data} + 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..82e586ef1 100644 --- a/qiita_pet/static/css/style.css +++ b/qiita_pet/static/css/style.css @@ -18,10 +18,20 @@ 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{ + cursor: pointer; + background: url('../img/details_close.png') no-repeat center center; +} + +div.details-control{ + cursor: pointer; + background: url('../img/details_open.png') no-repeat center center; +} +tr.shown div.details-control{ + cursor: pointer; + background: url('../img/details_close.png') no-repeat center center; } .blinking-message { @@ -43,7 +53,6 @@ tr.shown td.more-info-processing-jobs { display: block; } - .info-menu { word-wrap: break-word; white-space: normal; @@ -76,43 +85,3 @@ tr.shown td.more-info-processing-jobs { 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 d3a4de4ac..2b4a3d89b 100644 --- a/qiita_pet/templates/list_studies.html +++ b/qiita_pet/templates/list_studies.html @@ -5,11 +5,6 @@ - @@ -18,33 +13,27 @@