generated from bokulich-lab/q2-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ENH: group BUSCO stats into collapsible sections for better display (#…
…148) Co-authored-by: Santiago Castro Dau <[email protected]>
- Loading branch information
Showing
47 changed files
with
2,336 additions
and
1,685 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
{% extends "tabbed.html" %} | ||
|
||
{% block head %} | ||
<title>Embedding Vega-Lite</title> | ||
<script src="js/bootstrapMagic.js" type="text/javascript"></script> | ||
<link href="css/styles.css" rel="stylesheet" /> | ||
<script type="text/javascript"> | ||
// temporary hack to make it look good with Bootstrap 5 | ||
removeBS3refs(); | ||
</script> | ||
<script src="https://cdn.jsdelivr.net/npm//vega@5" type="text/javascript"></script> | ||
<script src="https://cdn.jsdelivr.net/npm//[email protected]" type="text/javascript"></script> | ||
<script src="https://cdn.jsdelivr.net/npm//vega-embed@6" type="text/javascript"></script> | ||
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha256-YvdLHPgkqJ8DVUxjjnGVlMMJtNimJ6dYkowFFvp4kKs=" rel="stylesheet"/> | ||
{% endblock %} | ||
|
||
{% block tabcontent %} | ||
<script crossorigin="anonymous" integrity="sha256-9SEPo+fwJFpMUet/KACSwO+Z/dKMReF9q4zFhU/fT9M=" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> | ||
|
||
<br> | ||
<div class="row row-cols-1 row-cols-md-2 g-4"> | ||
<div class="col-lg-12"> | ||
<div class="card mt-3 h-10"> | ||
<h5 class="card-header">Plot description</h5> | ||
<div class="card-body"> | ||
<p> | ||
The left plot shows the results generated by BUSCO for <b>all MAGs</b> and | ||
<b> samples</b>. "BUSCO attempts to provide a quantitative assessment | ||
of the completeness in terms of the expected gene content of a genome | ||
assembly, transcriptome, or annotated gene set. The results are | ||
simplified into categories of complete and single-copy, complete and | ||
duplicated, fragmented, or missing BUSCOs. BUSCO completeness results | ||
make sense only in the context of the biology of your organism". Visit the | ||
<a href="https://busco.ezlab.org/busco_userguide.html#interpreting-the-results">BUSCO User Guide </a> | ||
for more information. | ||
</p> | ||
<p> | ||
The right barplot shows assembly statistics calculated for each MAG using BBTools. | ||
Specifically, it displays the statistics computed by the <b>stats.sh</b> procedure from BBMap. | ||
View the | ||
<a href="https://github.com/BioInfoTools/BBMap/blob/master/sh/stats.sh"> | ||
source code and documentation | ||
</a> | ||
of stats.sh for more information. | ||
</p> | ||
|
||
<div style="align-items: center; display: flex"> | ||
<span class="header-inline">Downloads:</span> | ||
<div class="'col-lg-4"> | ||
<div aria-label="Basic outlined example" class="btn-group" role="group"> | ||
<a class="btn btn-outline-secondary" href="busco_results.csv">BUSCO results (csv)</a> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="card mt-3 h-10"> | ||
<h5 class="card-header">Plot controls</h5> | ||
<div class="card-body"> | ||
<p> | ||
To prevent data overload, the samples are grouped into collapsible sections below. You can | ||
expand/collapse each section by clicking on the little arrow on the right side of the section header. | ||
Each section will contain a maximum of 100 bins. | ||
<br><br> | ||
If you want to find statistics for a specific sample, you can pick your sample from the dropdown below - | ||
this will find the appropriate section and expand it. | ||
<br><br> | ||
You can hover over the bars to obtain information about the lineage dataset used for each MAG, | ||
and the number of genes in each BUSCO category. Additionally, you can choose the assembly statistic | ||
that you wish to display from the dropdown menu included in every section. | ||
</p> | ||
<div id="plot-controls"> | ||
<div style="align-items: center; display: flex;"> | ||
<span class="header-inline">Find sample:</span> | ||
<div class="col-lg-4"> | ||
<div class="btn-group" role="group"> | ||
<div class="dropdown"> | ||
<button class="btn btn-secondary dropdown-toggle" type="button" id="sampleSelector" data-bs-toggle="dropdown" aria-expanded="false"> | ||
</button> | ||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1" id="sampleSelectorElements"></ul> | ||
</div> | ||
<button id="collapseAllButton" class="btn btn-outline-secondary" type="submit" style="white-space: nowrap;">Collapse all</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="row"> | ||
<div class="col-lg-12"> | ||
<div id="plot"> | ||
<div class="accordion" id="accordionSamples"></div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<script id="vega_json" type="application/json"> | ||
{{ vega_json | safe }} | ||
</script> | ||
|
||
<script type="text/javascript"> | ||
function createAccordionItem(sampleFrom, sampleTo, show) { | ||
// Create elements | ||
const accordionItem = document.createElement('div'); | ||
const accordionHeader = document.createElement('h2'); | ||
const accordionButton = document.createElement('button'); | ||
const accordionCollapse = document.createElement('div'); | ||
const accordionBody = document.createElement('div'); | ||
|
||
// Set attributes and content | ||
accordionItem.className = 'accordion-item'; | ||
accordionHeader.className = 'accordion-header'; | ||
// accordionHeader.id = 'headingOne'; | ||
accordionButton.className = 'accordion-button'; | ||
accordionButton.type = 'button'; | ||
accordionButton.setAttribute('data-bs-toggle', 'collapse'); | ||
accordionButton.setAttribute('data-bs-target', `#collapse-${sampleFrom}`); | ||
// accordionButton.setAttribute('aria-expanded', 'true'); | ||
accordionButton.setAttribute('aria-controls', `collapse-${sampleFrom}`); | ||
accordionButton.textContent = `Samples ${sampleFrom} to ${sampleTo}`; | ||
accordionCollapse.id = `collapse-${sampleFrom}`; | ||
if (show) { | ||
accordionCollapse.className = 'accordion-collapse collapse show'; | ||
} else { | ||
accordionCollapse.className = 'accordion-collapse collapse'; | ||
} | ||
// accordionCollapse.setAttribute('aria-labelledby', 'headingOne'); | ||
accordionCollapse.setAttribute('data-bs-parent', '#accordionSamples'); | ||
accordionBody.className = 'accordion-body'; | ||
accordionBody.id = `accordion-${sampleFrom}`; | ||
|
||
// Append elements | ||
accordionHeader.appendChild(accordionButton); | ||
accordionItem.appendChild(accordionHeader); | ||
accordionCollapse.appendChild(accordionBody); | ||
accordionItem.appendChild(accordionCollapse); | ||
|
||
return accordionItem; | ||
} | ||
|
||
function createDropdownItem(sampleName) { | ||
const listItem = document.createElement("li"); | ||
const link = document.createElement("a"); | ||
link.className = "dropdown-item"; | ||
link.href = "#"; | ||
link.textContent = sampleName; | ||
listItem.appendChild(link); | ||
return listItem; | ||
} | ||
|
||
function populateDropdown(spec) { | ||
const sampleSelector = document.getElementById("sampleSelectorElements"); | ||
let samples = []; | ||
Object.entries(spec).forEach( | ||
([_, specElement]) => { | ||
let sampleIds = specElement["sample_ids"]; | ||
samples = [...samples, ...sampleIds]; | ||
} | ||
); | ||
console.log("All the samples:", samples); | ||
for (let i = 0; i < samples.length; i++) { | ||
const listItem = createDropdownItem(samples[i]); | ||
sampleSelector.appendChild(listItem); | ||
} | ||
document.getElementById("sampleSelector").textContent = samples[0]; | ||
} | ||
|
||
function findFromValue(dictionary, sampleId) { | ||
for (let [key, value] of Object.entries(dictionary)) { | ||
if (value.sample_ids.includes(sampleId)) { | ||
return value.sample_counter.from; | ||
} | ||
} | ||
return null; // return null if the sampleId is not found in any sample_ids array | ||
} | ||
|
||
function handleDropdownClick(event, spec, collapsibles) { | ||
const sampleName = event.target.innerText; // Get value from dataset | ||
const fromValue = findFromValue(spec, sampleName); | ||
|
||
// Update the dropdown button text | ||
document.getElementById("sampleSelector").textContent = sampleName; | ||
|
||
// Hide all collapsibles | ||
collapsibles.forEach(collapsible => { | ||
collapsible.classList.remove("show"); | ||
}); | ||
|
||
// Show the selected collapsible (if a value is selected) | ||
if (fromValue) { | ||
const targetCollapsible = document.getElementById(`collapse-${fromValue}`); | ||
targetCollapsible.classList.add('show'); | ||
} | ||
} | ||
|
||
$(document).ready(function () { | ||
// temporary hack to make it look good with Bootstrap 5 | ||
adjustTagsToBS3() | ||
|
||
const spec = JSON.parse(document.getElementById('vega_json').textContent); | ||
let count = 0; | ||
Object.entries(spec).forEach(([_, specElement]) => { | ||
const sampleCounter = specElement["sample_counter"]; | ||
const sampleFrom = sampleCounter["from"]; | ||
const sampleTo = sampleCounter["to"]; | ||
|
||
if (count === 0) { | ||
document.getElementById("accordionSamples") | ||
.appendChild(createAccordionItem(sampleFrom, sampleTo, true)); | ||
} else { | ||
document.getElementById("accordionSamples") | ||
.appendChild(createAccordionItem(sampleFrom, sampleTo, false)); | ||
} | ||
count += 1; | ||
|
||
vegaEmbed(`#accordion-${sampleFrom}`, specElement["subcontext"]).then( | ||
function (result) { | ||
result.view.logLevel(vega.Warn); | ||
window.v = result.view; | ||
} | ||
).catch( | ||
function (error) { | ||
handleErrors([error], $(`#accordion-${sampleFrom}`)); | ||
} | ||
); | ||
}); | ||
|
||
populateDropdown(spec); | ||
|
||
const dropdownMenu = document.getElementById("sampleSelectorElements"); | ||
const collapsibles = document.querySelectorAll(".collapse.accordion-collapse"); | ||
|
||
// Add event listener to the dropdown menu (ul) | ||
dropdownMenu.addEventListener('click', function(event) { | ||
handleDropdownClick(event, spec, collapsibles); | ||
}); | ||
|
||
const collapseAllButton = document.getElementById("collapseAllButton"); | ||
// Add event listener to thecollapse button | ||
collapseAllButton.addEventListener('click', function(event) { | ||
collapsibles.forEach(collapsible => { | ||
collapsible.classList.remove("show"); | ||
}); | ||
}); | ||
|
||
}); | ||
</script> | ||
|
||
{% endblock %} | ||
|
||
{% block footer %} | ||
{% set loading_selector = '#loading' %} | ||
{% include 'js-error-handler.html' %} | ||
{% endblock %} |
Oops, something went wrong.