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
- Loading branch information
Showing
3 changed files
with
255 additions
and
98 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,87 +6,78 @@ | |
// 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" | ||
/> | ||
<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 content %} | ||
<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> | ||
<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> | ||
|
||
<div class="row row-cols-1 row-cols-md-2 g-4"> | ||
<div class="col-lg-12"> | ||
<div class="card mt-3 h-100"> | ||
<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 bins</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 | ||
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 | ||
> | ||
<a href="https://busco.ezlab.org/busco_userguide.html#interpreting-the-results">BUSCO User Guide </a> | ||
for more information. | ||
</p> | ||
<p> | ||
Hoover over the graph to obtain information about the lineage dataset | ||
used for each bin, and the number of genes in each BUSCO category. | ||
</p> | ||
<p> | ||
The right barplot shows assembly statistics calculated for each bin 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" | ||
> | ||
<a href="https://github.com/BioInfoTools/BBMap/blob/master/sh/stats.sh"> | ||
source code and documentation | ||
</a> | ||
of stats.sh for more information. | ||
</p> | ||
<p> | ||
Choose the assembly statistic that you wish to display from the drop-down manu below the graphs. | ||
Hoover over the graph to show the numerical values that each bar represents. | ||
</p> | ||
|
||
<div style="align-items: center; display: flex"> | ||
<span class="header-inline">Downloads</span> | ||
<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="all_batch_summeries.csv" | ||
>BUSCO batch summary for all samples (csv)</a | ||
> | ||
<a class="btn btn-outline-secondary" href="BUSCO_plots.zip" | ||
>BUSCO plots for all samples (zip)</a | ||
> | ||
<div aria-label="Basic outlined example" class="btn-group" role="group"> | ||
<a class="btn btn-outline-secondary" href="all_batch_summaries.csv">BUSCO batch summary for all samples (csv)</a> | ||
<a class="btn btn-outline-secondary" href="BUSCO_plots.zip">BUSCO plots for all samples (zip)</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 bin, | ||
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> | ||
|
@@ -96,43 +87,161 @@ <h5 class="card-header">Plot description</h5> | |
</div> | ||
|
||
<div class="row"> | ||
{% if vega_plots_overview is defined %} | ||
<div class="col-lg-6"> | ||
<div id="plot"></div> | ||
<div id="plot-controls"></div> | ||
<div class="col-lg-12"> | ||
<div id="plot"> | ||
<div class="accordion" id="accordionSamples"></div> | ||
</div> | ||
</div> | ||
{% else %} | ||
<p>Unable to generate the completeness plot</p> | ||
{% endif %} | ||
</div> | ||
|
||
{% if vega_plots_overview is defined %} | ||
<script id="spec" type="application/json"> | ||
{{ | ||
vega_plots_overview | ||
}} | ||
<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 () { | ||
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; | ||
|
||
const spec = JSON.parse(document.getElementById("spec").innerHTML); | ||
vegaEmbed(`#accordion-${sampleFrom}`, specElement["subcontext"]).then( | ||
function (result) { | ||
result.view.logLevel(vega.Warn); | ||
window.v = result.view; | ||
} | ||
).catch( | ||
function (error) { | ||
handleErrors([error], $(`#accordion-${sampleFrom}`)); | ||
} | ||
); | ||
}); | ||
|
||
vegaEmbed("#plot", spec) | ||
.then(function (result) { | ||
result.view.logLevel(vega.Warn); | ||
window.v = result.view; | ||
populateDropdown(spec); | ||
|
||
// move the sliders to the right | ||
const controls = document.getElementsByClassName("vega-bindings"); | ||
document.getElementById("plot-controls").appendChild(controls[0]); | ||
}) | ||
.catch(function (error) { | ||
// From 'js-error-handler.html' | ||
handleErrors([error], $("#plot")); | ||
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> | ||
|
||
{% endif %} {% endblock %} {% block footer %} {% set loading_selector = | ||
{% endblock %} {% block footer %} {% set loading_selector = | ||
'#loading' %} {% include 'js-error-handler.html' %} {% endblock %} |
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
Oops, something went wrong.