function waitDialog() {
bootbox.dialog({
title: "Clade Classification",
message: '
Uploading data
'
});
}
//TODO: find correct parameter
bootbox.animate = false;
class Haplogroups {
colors = ['#4E79A7', '#A0CBE8', '#F28E2B', '#FFBE7D', '#59A14F', '#8CD17D',
'#B6992D', '#F1CE63', '#499894', '#86BCB6', '#E15759', '#FF9D9A', '#79706E',
'#BAB0AC', '#D37295', '#FABFD2', '#B07AA1', '#D4A6C8', '#9D7660', '#D7B5A6'
];
chart;
dataset;
index = 0;
constructor(id) {
this.id = id;
}
setDataset(dataset) {
this.dataset = dataset;
}
setIndex(index) {
this.index = index;
}
draw() {
this.destroy();
var group = this.dataset.groups[this.index];
var data = {
labels: group.clades,
datasets: [{
label: 'Samples',
data: group.values,
hoverOffset: 4,
backgroundColor: group.colors ? group.colors : this.colors
}]
};
var config = {
type: 'doughnut',
data: data,
options: {
plugins: {
legend: {
labels: {
boxWidth: 20
}
}
},
animation: {
animateRotate: false
}
},
responsive: true,
maintainAspectRatio: false
};
this.chart = new Chart(document.getElementById(this.id), config);
}
destroy() {
if (this.chart != undefined) {
this.chart.destroy();
this.chart = undefined;
}
}
}
class SamplesTable {
id;
maxMutations = 8;
table;
samples;
phylotree;
filter = 'all';
server = '';
constructor(id) {
this.id = id;
}
setSamples(samples) {
this.samples = samples;
}
setPhylotree(phylotree) {
this.phylotree = phylotree;
}
setServer(serverUrl) {
this.serverUrl = serverUrl;
}
render() {
this.destroy();
var self = this;
this.table = $("#" + this.id).DataTable({
pageLength: 50,
lengthChange: false,
fixedHeader: {
headerOffset: $('#navigation').outerHeight()
},
data: samples,
"columns": [{
data: "hasError",
"render": function(data, type, row) {
if (type == 'display') {
return self.renderIcon(row);
} else {
return self.renderText(row);
}
},
width: "20px"
}, {
"data": "sample"
}, {
"data": "clade"
}, {
"render": function(data, type, row) {
return self.renderProgressBar(row.quality);
}
}, {
"data": "ns",
width: "20px"
}, {
"data": "coverage"
}, {
"data": "ranges",
"render": function(data) {
return data.length + ' ranges';
}
}, {
"data": "annotatedPolymorphisms",
"render": function(data, type) {
if (type == 'display') {
return self.formatMutations(data);
} else {
return self.renderMutations(data);
}
}
}],
order: [
[1, 'asc']
],
"createdRow": function(row, data, dataIndex) {
if (data.errors.length > 0) {
$(row).addClass('table-danger');
return;
}
if (data.warnings.length > 0) {
$(row).addClass('table-warning');
return;
}
}
});
var self = this;
//check to bind it to a correct instance?
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
if (self.filter === "all" || data[0] == self.filter) {
return true;
}
return false;
}
);
$('#' + this.id + ' tbody').on('click', 'tr', function() {
var data = self.table.row(this).data();
new SamplesDetails(self.phylotree, data, self.serverUrl).show();
});
}
setSampleFilter(filter) {
this.filter = filter;
if (this.table != undefined) {
this.table.draw();
}
}
setMaxMutations(maxMutations) {
this.maxMutations = maxMutations;
if (this.table != undefined) {
this.table.rows().invalidate().draw();
}
}
search(query){
this.table.search(query).draw() ;
}
formatMutations(data) {
var result = '';
for (var i = 0; i < data.length && i < this.maxMutations; i++) {
var label = data[i].nuc;
var found = data[i].found;
if (result != '') {
result += ' ';
}
result += '' + label + '';
}
if (data.length > this.maxMutations) {
result += ' and ' + (data.length - this.maxMutations) + ' more';
}
return result;
}
renderMutations(data) {
var result = '';
for (var i = 0; i < data.length; i++) {
var label = data[i].nuc;
if (result != '') {
result += ' ';
}
result += label;
};
return result;
}
renderProgressBar(value) {
var percentage = value * 100;
return '' +
'
' +
'Quality: ' + value.toFixed(2) + '' +
'
' +
'
';
}
renderIcon(data) {
if (data.errors.length > 0) {
return '';
}
if (data.warnings.length > 0) {
return '';
}
return '';
}
renderText(data) {
if (data.errors.length > 0) {
return 'error';
}
if (data.warnings.length > 0) {
return 'warning';
}
return 'ok';
}
//adjust column size on tab switch
autoSize() {
this.table.columns.adjust();
}
destroy() {
if (this.table) {
this.table.destroy();
}
}
}
class SamplesDetails {
phylotree;
selectedMutation = undefined;
constructor(phylotree, data, serverUrl) {
this.phylotree = phylotree;
this.data = data;
this.serverUrl = serverUrl;
}
show() {
var self = this;
var dialog = bootbox.dialog({
title: self.renderIcon(self.data) + ' ' + self.data.sample,
onEscape: true,
buttons: {
close: {
label: 'Close',
className: 'btn-primary',
callback: function() {
}
}
},
message: '' +
'' +
'
' +
'
' +
'
' +
'
' +
' ' + self.formatDetails() +
'
' +
'
' +
'
' +
'
' +
'
' +
' ' + self.renderMutationDetails() +
'
' +
'
' +
'
' +
'
'
});
dialog.find("div.modal-dialog").addClass("scroll-modal-body-horizontal");
$(".mutation").on("click", function() {
self.showMutationDetails(this, self.serverUrl);
});
}
showMutationDetails(source, server) {
if (this.selectedMutation) {
$(this.selectedMutation).removeClass("selected-mutation");
}
this.selectedMutation = source;
$(source).addClass("selected-mutation");
var mutation = $(source).data("mutation");
var clade = $(source).data("clade");
var url = server + '/phylogenies/' + this.phylotree + '/haplogroups/' + clade + '/mutations/' + mutation + '?minimal=true';
$("#details").attr('src', url);
}
renderMutationDetails() {
return '';
}
renderIcon(data) {
if (data.errors.length > 0) {
return '';
}
if (data.warnings.length > 0) {
return '';
}
return '';
}
formatDetails() {
var topHitUrl = '/phylogenies/' + this.phylotree + '/haplogroups/' + this.data.clade;
var topHit = '' +
'Top Hit
' +
'' + this.data.clade + '' +
' (' + this.data.quality.toFixed(2) * 100 + '%)' +
'
';
var expectedMutation = '' +
'Expected Mutations ' +
' ' +
' ' +
'
' +
this.formatExpectedMutations() +
'
';
var remainingMutations = '' +
'Remaining Mutations ' +
' ' +
' ' +
'
' +
this.formatRemainingMutations() +
'
';
var additionalHits = '' +
'Additional Hits
' +
this.formatHits() +
'
';
var ranges = '' +
'Ranges
' +
this.formatRange() +
'
';
return this.renderWarningsAndErrors() +
topHit +
expectedMutation +
remainingMutations +
additionalHits +
ranges;
}
formatExpectedMutations() {
var result = '';
for (var i = 0; i < this.data.expectedMutations.length; i++) {
var mutation = this.data.expectedMutations[i];
var label = mutation.nuc;
var found = mutation.found;
var id = mutation.position + '_' + mutation.ref + '_' + mutation.alt;
if (result != '') {
result += ' ';
}
result += '' +
label +
'';
};
return result;
}
formatRemainingMutations() {
var result = '';
for (var i = 0; i < this.data.remainingMutations.length; i++) {
var mutation = this.data.remainingMutations[i];
var label = mutation.nuc;
var type = mutation.type;
var id = mutation.position + '_' + mutation.ref + '_' + mutation.alt;
if (result != '') {
result += ' ';
}
result += '' + label + '';
};
return result;
}
formatRange() {
var result = '';
for (var i = 0; i < this.data.ranges.length; i++) {
var label = this.data.ranges[i].trim();
if (label != undefined && label != '') {
if (result != '') {
result += ' ';
}
result += '' + label + '';
}
};
return result;
}
formatHits() {
var result = '' +
'
' +
'';
for (var i = 0; i < this.data.otherClades.length; i++) {
var hit = this.data.otherClades[i];
var quality = this.data.otherQualities[i];
var url = '/phylogenies/' + this.phylotree + '/haplogroups/' + hit;
var link = '' + hit + '';
result += '- ' + link + ' (' + quality.toFixed(2) * 100 + '%)
';
};
result += '
' +
'' +
'
';
return result;
}
renderWarningsAndErrors() {
var result = "";
result += this.renderIssues(this.data.errors, "danger");
result += this.renderIssues(this.data.warnings, "warning");
result += this.renderIssues(this.data.infos, "info");
return result;
}
renderIssues(issues, type) {
var result = "";
for (var i = 0; i < issues.length; i++) {
var label = issues[i].trim();
result += '' + label + '
';
}
return result;
}
}
console.log("Loaded app.js");