Skip to content

redbiom now adds per sample studies to analysis #2288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions qiita_pet/handlers/qiita_redbiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# -----------------------------------------------------------------------------

from requests import ConnectionError
from future.utils import viewitems
from collections import defaultdict
import redbiom.summarize
import redbiom.search
Expand Down Expand Up @@ -42,35 +43,38 @@ def _redbiom_metadata_search(self, query, contexts):
'Not a valid search: "%s", your query is too small '
'(too few letters), try a longer query' % query)
if not message:
sids = set([s.split('.', 1)[0] for s in samples])
for s in sids:
study_artifacts[s] = [a.id for a in Study(s).artifacts(
artifact_type='BIOM')]
study_samples = defaultdict(list)
for s in samples:
study_samples[s.split('.', 1)[0]].append(s)
for sid, samps in viewitems(study_samples):
study_artifacts[sid] = {
a.id: samps for a in Study(sid).artifacts(
artifact_type='BIOM')}

return message, study_artifacts

def _redbiom_feature_search(self, query, contexts):
study_artifacts = defaultdict(list)
study_artifacts = defaultdict(lambda: defaultdict(list))
query = [f for f in query.split(' ')]
for ctx in contexts:
for idx in redbiom.util.ids_from(query, True, 'feature', ctx):
aid, sid = idx.split('_', 1)
sid = sid.split('.', 1)[0]
study_artifacts[sid].append(aid)
aid, sample_id = idx.split('_', 1)
sid = sample_id.split('.', 1)[0]
study_artifacts[sid][aid].append(sample_id)

return '', study_artifacts

def _redbiom_taxon_search(self, query, contexts):
study_artifacts = defaultdict(list)
study_artifacts = defaultdict(lambda: defaultdict(list))
for ctx in contexts:
# find the features with those taxonomies and then search
# those features in the samples
features = redbiom.fetch.taxon_descendents(ctx, query)
for idx in redbiom.util.ids_from(features, True, 'feature',
ctx):
aid, sid = idx.split('_', 1)
sid = sid.split('.', 1)[0]
study_artifacts[sid].append(aid)
aid, sample_id = idx.split('_', 1)
sid = sample_id.split('.', 1)[0]
study_artifacts[sid][aid].append(sample_id)

return '', study_artifacts

Expand Down Expand Up @@ -98,8 +102,8 @@ def _redbiom_search(self, query, search_on, callback):
study_artifacts.keys(), True)
# inserting the artifact_biom_ids to the results
for i in range(len(results)):
results[i]['artifact_biom_ids'] = list(set(
study_artifacts[str(results[i]['study_id'])]))
results[i]['artifact_biom_ids'] = study_artifacts[
str(results[i]['study_id'])]
else:
message = "No samples where found! Try again ..."
else:
Expand Down
64 changes: 50 additions & 14 deletions qiita_pet/static/js/qiita.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,25 +149,35 @@ function show_hide_process_list() {
* Note that we have a list of artifact ids cause the user can select one single
* artifact to add or all study artifacts
*/
function send_samples_to_analysis(button, aids) {
function send_samples_to_analysis(button, aids, samples = null) {
button.value = 'Adding';
button.disabled = true;
$(button).addClass("btn-info");
bootstrapAlert('We are adding ' + aids.length + ' artifact(s) to the analysis. This ' +
'might take some time based on the number of samples on each artifact.', "warning", 10000);
$.get('/artifact/samples/', {ids:aids})
.done(function ( data ) {
if (data['status']=='success') {
qiita_websocket.send('sel', data['data']);
button.value = 'Added';
$(button).removeClass("btn-info");
} else {
bootstrapAlert('ERROR: ' + data['msg'], "danger");
button.value = 'There was an error, scroll up to see it';
button.disabled = false;
$(button).addClass("btn-danger");
}
if (samples === null) {
$.get('/artifact/samples/', {ids:aids})
.done(function ( data ) {
if (data['status']=='success') {
qiita_websocket.send('sel', data['data']);
button.value = 'Added';
$(button).removeClass("btn-info");
} else {
bootstrapAlert('ERROR: ' + data['msg'], "danger");
button.value = 'There was an error, scroll up to see it';
button.disabled = false;
$(button).addClass("btn-danger");
}
});
} else {
$.each(aids, function(i, aid) {
var to_send = {};
to_send[aid] = samples.split(',');
qiita_websocket.send('sel', to_send);
});
button.value = 'Added';
$(button).removeClass("btn-info");
}
}

/**
Expand Down Expand Up @@ -388,25 +398,51 @@ function show_alert(data) {
$('#dflt-sel-info').css('color', 'rgb(0, 160, 0)');
}

function format_biom_rows(data, row) {
function format_biom_rows(data, row, for_study_list = true, samples = null) {
var proc_data_table = '<table class="table" cellpadding="0" cellspacing="0" border="0" style="padding-left:0px;width:95%">';
proc_data_table += '<tr>';
if (for_study_list) {
proc_data_table += '<th></th>';
}
proc_data_table += '<th>Name</th>';
if (for_study_list) {
proc_data_table += '<th>Data type</th>';
}
proc_data_table += '<th>Processing method</th>';
proc_data_table += '<th>Parameters</th>';
if (for_study_list) {
proc_data_table += '<th>Samples in Prep Info</th>';
}
proc_data_table += '<th>Files</th>';
proc_data_table += '</tr>';

$.each(data, function (idx, info) {
if (typeof info !== 'string' && !(info instanceof String)) {
proc_data_table += '<tr>';
if (for_study_list) {
if (samples === null) {
proc_data_table += '<td><input type="button" class="btn btn-sm" value="Add" onclick="send_samples_to_analysis(this, [' + info.artifact_id + '])"></td>';
} else {
proc_data_table += '<td><input type="button" class="btn btn-sm" value="Add" onclick="send_samples_to_analysis(this, [' + info.artifact_id + "], '" + samples[info.artifact_id].join(',') + "'" + ')"></td>';
}
}
proc_data_table += '<td>' + info.name + ' (' + info.artifact_id + ' - ' + info.timestamp.split('.')[0] + ')</td>';

if (for_study_list) {
proc_data_table += '<td>' + info.data_type + ' (' + info.target_subfragment.join(', ') + ')</td>';
}
proc_data_table += '<td>' + info.algorithm + '</td>';

var params = '';
for (var key in info.parameters) {
params += '<i>' + key + '</i>: ' + info.parameters[key] + '<br/>';
}
proc_data_table += '<td><small>' + params + '</small></td>';
if (for_study_list) {
proc_data_table += '<td>' + info.prep_samples + '</td>';
}
proc_data_table += '<td><small>' + info.files.join('<br/>') + '</small></td>';

proc_data_table += '</tr>';
}
});
Expand Down
2 changes: 1 addition & 1 deletion qiita_pet/templates/artifact_ajax/artifact_summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ <h4>
{% if editable %}
<a class="btn btn-default btn-sm" data-toggle="modal" data-target="#update-artifact-name"><span class="glyphicon glyphicon-pencil"></span> Edit</a>
{% if artifact_type == 'BIOM' %}
<a class="btn btn-default btn-sm" onclick="send_samples_to_analysis(this, [{{artifact_id}}]);"> Add to analysis</a>
<input type="button" class="btn btn-default btn-sm" value="Add to Analysis" onclick="send_samples_to_analysis(this, [{{artifact_id}}]);">
{% else %}
<a class="btn btn-default btn-sm" onclick="load_process_artifact_ui({{artifact_id}});"><span class="glyphicon glyphicon-play"></span> Process</a>
{% end %}
Expand Down
2 changes: 1 addition & 1 deletion qiita_pet/templates/list_analyses.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
$.get('/artifact/info/', {ids: JSON.parse(row.data()[0]), only_biom: 'False' })
.done(function ( data ) {
if (data['status']=='success') {
$('td', row.child()).html(format_biom_rows(data.data, row.index())).show();
$('td', row.child()).html(format_biom_rows(data.data, row.index(), for_study_list=false)).show();
} else {
bootstrapAlert('ERROR: ' + data['msg'], "danger", 10000);
}
Expand Down
35 changes: 0 additions & 35 deletions qiita_pet/templates/list_studies.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,41 +54,6 @@
$("#search-waiting").hide();
qiita_websocket.init(window.location.host + '{% raw qiita_config.portal_dir %}/study/list/socket/', error, error);
qiita_websocket.add_callback('sel', show_alert);
function format_biom_rows(data, row) {
var proc_data_table = '<table class="table" cellpadding="0" cellspacing="0" border="0" style="padding-left:0px;width:95%">';
proc_data_table += '<tr>';
proc_data_table += '<th></th>';
proc_data_table += '<th>Name</th>';
proc_data_table += '<th>Data type</th>';
proc_data_table += '<th>Processing method</th>';
proc_data_table += '<th>Parameters</th>';
proc_data_table += '<th>Samples in Prep Info</th>';
proc_data_table += '<th>Files</th>';
proc_data_table += '</tr>';

$.each(data, function (idx, info) {
if (typeof info !== 'string' && !(info instanceof String)) {
proc_data_table += '<tr>';
proc_data_table += '<td><input type="button" class="btn btn-sm" value="Add" onclick="send_samples_to_analysis(this, [' + info.artifact_id + '])"></td>';
proc_data_table += '<td>' + info.name + ' (' + info.artifact_id + ' - ' + info.timestamp.split('.')[0] + ')</td>';
proc_data_table += '<td>' + info.data_type + ' (' + info.target_subfragment.join(', ') + ')</td>';
proc_data_table += '<td>' + info.algorithm + '</td>';

var params = '';
for (var key in info.parameters) {
params += '<i>' + key + '</i>: ' + info.parameters[key] + '<br/>';
}
proc_data_table += '<td><small>' + params + '</small></td>';
proc_data_table += '<td>' + info.prep_samples + '</td>';
proc_data_table += '<td><small>' + info.files.join('<br/>') + '</small></td>';

proc_data_table += '</tr>';
}
});

proc_data_table += '</table>';
return proc_data_table;
}

$('#user-studies-table').dataTable({
"lengthMenu": [[5, 10, 50, -1], [5, 10, 50, "All"]],
Expand Down
57 changes: 37 additions & 20 deletions qiita_pet/templates/redbiom.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,55 @@
// adding total features found

var api = this.api(), data;
var total_features = api
var artifacts_samples = api
.column(0)
.data()
.reduce( function (a, b) {return a + b.length}, 0);

.reduce( function (a, b) {
var artifacts = 0, samples = 0;
$.each( b, function( key, value ) {
artifacts += 1;
samples += value.length;
});
return [artifacts, samples]}, [0, 0]);
var artifacts = artifacts_samples[0];
var samples = artifacts_samples[1];
$('.footer').addClass("col-md-12 text-right");
if (total_features == 0) {
if (artifacts == 0) {
text = '';
} else {
text = 'Found ' + total_features + ' artifacts.';
text = 'Found ' + artifacts + ' artifacts with ' + samples + ' samples.';
}
$('.footer').html(text)
},
"columns": [
{ "orderable": false, "width": "15%", "data": "artifact_biom_ids"},
{ "orderable": false, "width": "20%", "data": "artifact_biom_ids"},
{ "data": "study_title", "width": "70%" },
{ "data": "study_abstract", "width": "0%" },
{ "data": "study_id", "width": "15%" },
{ "data": "study_id", "width": "10%" },
{ "data": "study_alias", "width": "0%" }],
columnDefs: [
// {type:'natural', targets:[2,6,7]},
{"targets": [ 2, 4 ], "visible": false},
// render zero
{"render": function ( data, type, row, meta ) {
if (data !== null && data !== undefined && data.length != 0){
return '<div class="container" style="max-width: 5em;">'+
'<div class="row justify-content-md-center">' +
{% if current_user is not None %}
'<div class="col-md-1 text-center details-control">&nbsp;</div>' +
{% end %}
'<div class="col-md-1 text-center">' + data.length + '</div>' +
'</div>' +
'</div>';
} else {
return 'No BIOMs';
if (data !== null && data !== undefined){
var artifacts = 0, samples = 0;
for (var d in data) { if (data.hasOwnProperty(d)) { artifacts++; } }
if (artifacts != 0) {
return '<div class="container" style="max-width: 15em;">'+
'<div class="row justify-content-md-center">' +
{% if current_user is not None %}
'<div class="col-md-12 text-center details-control">&nbsp;</div>' +
{% end %}
'<div class="col-md-12 text-center">' +
'Artifacts: ' + artifacts + ' | ' +
'Samples: ' + artifacts +
'</div>' +
'</div>' +
'</div>';
}
}
return 'No BIOMs';
}, targets: [0]},
// render the title cell
{"render": function ( data, type, row, meta ) {
Expand Down Expand Up @@ -85,10 +98,14 @@
// modified from: https://jsfiddle.net/8rejaL88/2/
tr.addClass('shown');
row.child('<p><center><img src="{% raw qiita_config.portal_dir %}/static/img/waiting.gif" style="display:block;margin-left: auto;margin-right: auto"/></center></p>', 'no-padding' ).show();
$.get('/artifact/info/', {ids: row.data().artifact_biom_ids})

var artifact_biom_ids = row.data().artifact_biom_ids;
var artifact_biom_ids_keys = []
$.each(artifact_biom_ids, function(e){ artifact_biom_ids_keys.push(e) });
$.get('/artifact/info/', {ids: artifact_biom_ids_keys })
.done(function ( data ) {
if (data['status']=='success') {
$('td', row.child()).html(format_biom_rows(data.data, row.index())).show();
$('td', row.child()).html(format_biom_rows(data.data, row.index(), true, samples=artifact_biom_ids)).show();
} else {
bootstrapAlert('ERROR: ' + data['msg'], "danger", 10000);
}
Expand Down
12 changes: 9 additions & 3 deletions qiita_pet/test/test_qiita_redbiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def test_post_metadata(self):
response = self.post('/redbiom/', post_args)
self.assertEqual(response.code, 200)
data = DATA
data[0]['artifact_biom_ids'] = [4, 5, 6, 7]
samples = ['1.SKD6.640190', '1.SKD9.640182', '1.SKD8.640184',
'1.SKD5.640186', '1.SKD2.640178', '1.SKD4.640185',
'1.SKD1.640179', '1.SKD3.640198', '1.SKD7.640191']
data[0]['artifact_biom_ids'] = {
'5': samples, '4': samples, '7': samples, '6': samples}
exp = {'status': 'success', 'message': '', 'data': data}
self.assertEqual(loads(response.body), exp)

Expand Down Expand Up @@ -59,7 +63,8 @@ def test_post_features(self):
}
response = self.post('/redbiom/', post_args)
data = DATA
data[0]['artifact_biom_ids'] = ['5', '4']
data[0]['artifact_biom_ids'] = {
'5': ['1.SKM3.640197'], '4': ['1.SKM3.640197']}
exp = {'status': 'success', 'message': '', 'data': data}
self.assertEqual(response.code, 200)
self.assertEqual(loads(response.body), exp)
Expand All @@ -80,7 +85,8 @@ def test_post_taxon(self):
'search_on': 'taxon'
}
data = DATA
data[0]['artifact_biom_ids'] = ['5', '4']
data[0]['artifact_biom_ids'] = {
'5': ['1.SKM3.640197'], '4': ['1.SKM3.640197']}
response = self.post('/redbiom/', post_args)
exp = {'status': 'success', 'message': '', 'data': data}
self.assertEqual(response.code, 200)
Expand Down